system_snake.c (70610B)
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 * System Snake 8 * 9 * This file runs a system-level snake test. Packets are injected into 10 * a set of closed loops running around the system and left to cycle for 11 * a period of time. At a certain interval, the counters are checked to 12 * confirm that traffic continues to flow. At the end of the test, the 13 * packets are drained and verified against the transmitted packets. 14 * The final counter values are displayed on success. 15 * 16 * Port speed used is default (set in rc.soc) unless overridden on cmd 17 * line. Full duplex is used for snake test. Loopback modes are MAC 18 * and PHY. EXT mode uses cables (crossover or straight) between ports 19 * 1&2, 3&4, 5&6, etc. Exposed HiGig ports are connected externally. 20 * 21 * Details: 22 * 23 * Initialization includes placing all of the ports into the proper 24 * forwarding and/or loopback state. VLANs are configured to include 25 * all ports. On 5690, the L2 table is programmed to forward the 26 * packets to the next destination. On 5670, the UC table is used. The 27 * packets are drained with filters. All packet I/O takes place on one 28 * 5690 for simplicity. 29 * 30 * The implementation borrows significantly from the test/lb_util.c 31 * library of loopback utilities. The packet I/O and verification 32 * routines, port interconnection functions, and counter monitoring 33 * procedures are the most important pieces of recycling. 34 * 35 * The default paths implemented here are 12 closed loops corresponding 36 * to a 5690 port number. That is, for a given path, a packet travels 37 * from port n on the first 5690 to port n on each succeeding 5690 (via 38 * the Higig uplinks to 5670). From the final 5690 in the system, the 39 * packet travel to the 5670 and loops externally out the back panel 40 * ports. Thus, the back panel ports must be connected in pairs by 41 * cable. After traveling these external loops, the packet is returned 42 * to the first 5690 unit and continues the cycle. The path is broken 43 * at the end of the test by means of a filter on the first 5690. 44 * 45 * The first section of this file contains a number of defines which 46 * might be tweaked to alter the parameters of the test. Changing the 47 * number of paths will require reworking the path interconnection 48 * declarations. Also, the test currently expects all ports to be 49 * involved. Omitting some paths or ports will produce a test failure. 50 * 51 * Exceeding bandwidth rates will result in dropped packets and test 52 * failure. For the 12 paths defined below, the 10 packets used in each 53 * path were experimentally determined. They result in traffic near 54 * line rate on the 5670; they also do not exceed the CPU's ability to 55 * drain packets before the system drops packets. 56 */ 57 58 /* 59 * This is the new implementation of the system snake test. It preserves 60 * all the functionality of the original tests and uses the same 61 * underlying functions to implement it. 62 * 63 * The new implementation goals were: 64 * 1) to make it easy to add new platforms and snake configurations without 65 * breaking the existing ones 66 * 2) to overcome certain restrictions contained in the original code in 67 * order to allow for more complex system/snake configurations. 68 * 69 * The first goal is accomplished by replacing the complicated, platform- 70 * dependent snake generation code with a simple generic function that 71 * generates snakes according to specially constructed tables (which 72 * are, indeed, platform-dependent). Now, adding a platform means adding 73 * new snake definitions rather than changing the code, debugging it and 74 * then testing that you haven't broken any other platforms. 75 * 76 * The new code also removes one of the major restrictions that the 77 * original code. Specifically it allows various snake paths to co-exist 78 * on the same platform. The code makes no assumption which chips is 79 * used to inject packets into the snake or where to drain them from -- 80 * this information is implicitly encoded in the snake path 81 * definition. The number of packets to be injected in the snake can 82 * also be now specified on a per-snake basis allowing for snakes with 83 * different speed/throughput to coexist. 84 * 85 * Adding a new platform: 86 * ====================== 87 * 88 * 1) Add a new member to the system names enum (SS_SYSID_XXX) right before 89 * SS_SYSID_NUM element 90 * 2) Add a platform name to the ss_sysid_str right before NULL. Make sure that 91 * the appropriate config variable is set on that box. For example, for 92 * the platform "foo" you should do "config add foo=1; config save" 93 * 3) Specify the correct unit bitmap (it has '1's for all units present in 94 * the box) in the ss_unit_bitmap array. For example, if your system has 95 * units 0, 1 and 2 the bitmap will be 0x7. 96 * 4) Define the basic snake path(s) for the new platform. 97 * Specify the number of paths in the ss_num_paths array. 98 * Check that the number of snake "vertebrae" (the number of elements in 99 * the conn array) does not exceed SS_MAX_SNAKE_CONN. 100 * If it does, please update the constant. 101 * 5) Create a snake list for the new platform. This list contains at least 1 102 * snake path, but is most handy when several snakes that differ only by 103 * port numbers should be created 104 * Check if the number of snakes for your platform exceeds SS_MAX_SNAKE. If 105 * does, please 106 * 6.1) Update the constant accordingly 107 * 6.2) Add additional MAC addresses to ss_mac_src and ss_mac_dst 108 * arrays. 109 * 6) Add the platform-specific snake list to the ss_snake_table array 110 * 111 * Defining a snake 112 * ================ 113 * 114 * A snake describes a (looped) path that test packet(s) will take 115 * through the the system. This path is system dependent and is designed 116 * for each of the supported systems separately. 117 * 118 * A snake has a number of "vertebrae" or, more formally, a list of 119 * connections. Each connection (see system_snake_conn_t type 120 * definition) defines where the packets that have been received on a 121 * specific unit on a specific port with a specific module ID should go 122 * and described by the following tuple: 123 * -- unit The unit number on which that specific connection 124 * should be configured 125 * -- src_mod The module ID of the arriving packet 126 * -- src_port On which port the packet arrives 127 * -- dst_mod What will be the new (rewritten) module ID 128 * -- dst_port Through which port the packet should get out of the 129 * chip (unit) 130 * -- flags Which of {src,dst}_{mod,port} should be modified 131 * (and how) based on the snake_port number on the 132 * snake list. 133 * 134 * Full snake definition includes: 135 * (a) the number of vertebrae, 136 * (b) the packet length increment that is applied as successive packets 137 * are transmitted, 138 * (c) the "return unit" which is the unit where the filter is set up 139 * to retrieve the packets at the end of the test, and 140 * (d) list of connections (see system_snake_path_t definition). 141 * 142 * The number of packets to be injected into/drained from the snake is 143 * definied rather implicitly by using packet_length_inc parameters, which 144 * specifies how the test packet lengths should be computed: from 145 * SS_PACKET_LENGTH_MIN to SS_PACKET_LENGTH_MAX with packet_length_inc 146 * length increments. Note that the packet length increment may be 147 * specified on the command line which will override the hardcoded settings. 148 * 149 * The first connection in the snake definition is also used to 150 * implicitly specify the unit that will be used to inject packets into 151 * the snake and drain them from it at the end of the test, although (as 152 * noted) the unit on which the filter is set up may differ for external 153 * loopbacks. 154 * 155 * Here is a definition of a snake for a Lancelot board with the 156 * explanations: 157 * 158 * Line 159 * 1 STATIC system_snake_path_t lancelot_snake_cw = { 160 * 2 8, 161 * 3 153, 162 * 4 { 163 * 5 { 1, 0, 0, 10, 0, SS_SP_PATH | SS_DP_PATH | SS_DM_PATH }, 164 * 6 { 0, 10, 7, 10, 6, SS_SM_PATH | SS_DM_PATH }, 165 * 7 { 0, 10, 5, 10, 4, SS_SM_PATH | SS_DM_PATH }, 166 * 8 { 0, 10, 3, 10, 2, SS_SM_PATH | SS_DM_PATH }, 167 * 9 { 4, 10, 12, 3, 0, SS_SM_PATH | SS_DP_PATH }, 168 * 10 { 4, 3, 0, 2, 0, SS_SP_PATH | SS_DP_PATH }, 169 * 11 { 3, 2, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 170 * 12 { 2, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 171 * 13 } 172 * 14 }; 173 * 174 * Line 1: Define a static initialized structure 175 * Line 2: The snake has 8 connections (vertebrae) 176 * Line 3: The packet length increment for the packets injected into the snake 177 * is 153, which will result in packet lengths SS_PACKET_LENGTH_MIN 178 * (68 bytes), SS_PACKET_LENGTH_MIN+153 (221 bytes), etc. 179 * Line 5: The snake originates on the chip 1 (the leftmost 5690). If a packet 180 * arrives on port 0 and has a module ID 0 (and belongs to the VLAN 181 * SS_VLAN_BASE + 0), then it is sent to the module with the modid 10 182 * port 0. This results in the packet being forwarded to the switch 183 * fabric via the HiGig interface. Flags indicate the for the packets 184 * starting from port N rather than 0, N should be added to the source 185 * port, destination port and destination module number. In addition, 186 * in case an external loopback mode is chosen, the destination port's 187 * LSB will be toggled. (see ss_port_interconnect_define()) 188 * Line 6: On unit 0 (5670 switch fabric) a packet arriving on port 7 (a HiGig 189 * connected to the leftmost 5690) with modid 10 should be forwarded 190 * to port 6 (one of the stacking HiGigs connected via an external 191 * loopbak cable to another external HiGig port (5)) 192 * Line 7: On unit 0 (5670 switch fabric) a packet arriving on port 5 193 * (an external HiGig port connected via loopback to port 6) 194 * with modid 10 should be forwarded to port 4 (another stacking HiGig 195 * port connected via an external loopbak cable to external HiGig 196 * port (3)) 197 * Line 8: On unit 0 (5670 switch fabric) a packet arriving on port 3 198 * (an external HiGig port connected via loopback to port 4) 199 * with modid 10 should be forwarded to port 2 (a HiGig port 200 * connected to the unit 4 (modid 3) which is te rightmost 5690) 201 * Line 9: On unit 4 (the right-most 5690), packets arriving via the HiGig 202 * port (12) with modid 10 should be forwarded to modid (3) port 0 203 * (basically port 0 on the same chip which is looped back to itself 204 * in MAC or PHY mode or port1 in the EXTERNAL mode). 205 * Line 10: On unit 4 (the right-most 5690), packets arriving on port 0 with 206 * modid 3 should be forwarded to port 0 on modid 2. 207 * Line 11: On unit 3 (the second from the right 5690), packets arriving on 208 * port 0 with modid 2 should be forwarded to port 0 on modid 1. 209 * Line 10: On unit 2 (the third from the right 5690), packets arriving on 210 * port 0 with modid 1 should be forwarded to port 0 on modid 0, which 211 * is the leftmost 5690 (unit 1) and this closes the snake. 212 * 213 ****************************************************************************** 214 * System Snake for Firebolt 48 port POE board 215 ****************************************************************************** 216 * Platform info: 217 * 218 * Firebolt 48 POE has two Firebolt (BCM56504) devices. These 2 devices 219 * are connected to each other through highGig Port 2 and 3. Highgig Port 220 * 0 and 1 come out of the board and 48 Gigabit ethernet ports come to the 221 * front panel. Ports highGig 0 and 1 are configured in 10 Gig Ethernet mode 222 * for system snake test. 223 * 224 * System snake can be run as both internal mode and external mode. 225 * 226 * In internal mode, there are 28 snakes: 227 * 228 * 24 snakes each of which connect from port X of Firebolt device 0 to 229 * port X of firebolt device 1. ports 0-11 use highGig port 2 and 230 * port 12-23 use highGig port 3. 231 * 232 * 2 snakes on device 0, one on XGE Port 0 and other on XGE port 1. 233 * 2 snakes on device 1, one on XGE Port 0 and other on XGE port 1. 234 * 235 * In external mode, there are 28 snakes: 236 * 237 * 12 snakes each of which goes from port X on device 0 to Port X+1. Packets 238 * are looped on device 1 from Port X+1 to Port X through external loopback 239 * cables to Port X+1 of device 0. These snakes apply for even port numbers 240 * for instance port 0, 2 .. 241 * For external loopback, each odd numbered port should be connected through 242 * loopback cable to port x+1 i.e. port 1 to port 2, port 3 to port 4 and so 243 * on. 244 * 245 * 246 * 12 snakes each of which goes from port X+1 on device 0 to Port X1. Packets 247 * are looped on device 1 from Port X to Port X+1 through external loopback 248 * cables to Port X of device 0. These snakes are applicable for odd numbered 249 * ports, eg port 1,3.. 250 * 251 * 2 snakes on device 0 between XGE Port 0 and 1 and vice versa, i.e. 252 * one between XGE0 to XGE1 and another between XGE1 to XGE0. 253 * 2 snakes on device 1 between XGE Port 0 and 1 and vice versa, i.e. 254 * one between XGE0 to XGE1 and another between XGE1 to XGE0. 255 */ 256 257 #ifdef INCLUDE_TEST 258 259 #include <sal/appl/sal.h> 260 #include <sal/appl/config.h> 261 #include <shared/bsl.h> 262 #include <soc/drv.h> 263 264 #include <bcm/error.h> 265 #include <bcm/tx.h> 266 #include <bcm/link.h> 267 #include <bcm/vlan.h> 268 #include <bcm/stat.h> 269 270 #include <appl/diag/system.h> 271 #include <appl/diag/test.h> 272 #include <appl/diag/dport.h> 273 274 #include <appl/test/loopback2.h> 275 276 #define SS_SOC_SCRIPT "syssnake.soc" 277 278 /* defines */ 279 #define SS_MAX_SNAKE 28 /* max number of test snakes */ 280 #define SS_MAX_SNAKE_CONN 12 /* maximum snake length */ 281 282 #define SS_PACKET_LENGTH_MIN 68 283 #define SS_PACKET_LENGTH_MAX 1516 284 #define SS_VLAN_BASE 100 285 #define SS_COS 0 286 #define SS_SEQUENCE_BASE 1 287 #define SS_PATTERN_BASE 0x11223344 288 #define SS_PATTERN_INC 0x01020304 289 290 /* Default settings (can be overridden on cmd line) */ 291 #define SS_DURATION 10 292 #define SS_INTERVAL 5 293 #define SS_INTERPATH_WAIT 100000 294 295 #define SS_UNIT_ITER(sysid, unit) \ 296 for ((unit) = 0; (unit) < SOC_MAX_NUM_DEVICES; (unit)++) \ 297 if (ss_unit_bitmap[(sysid)] & (1 << (unit))) 298 299 #define SS_PACKETS_PER_PATH(path ) \ 300 (((SS_PACKET_LENGTH_MAX - SS_PACKET_LENGTH_MIN) \ 301 / (path)->packet_length_inc) + 1) 302 303 304 /* enums */ 305 enum { 306 SS_SPEED_DEFAULT = 0, /* ss_speed_str and ss_speed_mbits */ 307 SS_SPEED_MAX, /* tables must match */ 308 SS_SPEED_10, 309 SS_SPEED_100, 310 SS_SPEED_1000, 311 SS_SPEED_2500, 312 SS_SPEED_3000, 313 SS_SPEED_10G, 314 SS_SPEED_NUM 315 }; 316 317 enum { 318 SS_MODE_MAC = 0, /* ss_mode_str table must match */ 319 SS_MODE_PHY, 320 SS_MODE_EXT, 321 SS_MODE_NUM 322 }; 323 324 /* 325 * The system names enum 326 */ 327 enum { 328 SS_SYSID_FIREBOLT, 329 SS_SYSID_FBPOE, 330 SS_SYSID_LM_FB48, 331 SS_SYSID_LM_FELIX48P, 332 SS_SYSID_ICS_EB, 333 SS_SYSID_GE_HU48, 334 SS_SYSID_FE_HU48, 335 SS_SYSID_NUM 336 }; 337 338 /* 339 * Flags for system snake definitions: 340 * SS_SP_PATH -- add snake number to the base source port 341 * SS_SM_PATH -- add snake number to the base source modid 342 * SS_DP_PATH -- add snake number to the base destination port 343 * and toggle the LSB in the resulting number in 344 * case we use external loopback 345 * SS_DM_PATH -- add snake number to the base destination port 346 * SS_DP_NOEXT -- do not toggle the last bit of the destination port number 347 * in the external loopback mode. This is used to implement 348 * external loopbacks on chips like 5673 that have only 1 349 * Ethernet (XG) port. For these chips external loopbacks 350 * are done by connecting Rx to Tx on the same chip. 351 */ 352 enum { 353 SS_SP_PATH = 0x00000001, 354 SS_SM_PATH = 0x00000002, 355 SS_DP_PATH = 0x00000004, 356 SS_DM_PATH = 0x00000008, 357 SS_DP_NOEXT = 0x00000010, 358 SS_DP_FORCE = 0x00000020 /* Force toggling of DP LSB for all modes */ 359 }; 360 361 /* typedefs */ 362 typedef struct system_snake_opts_s { 363 int sysid; /* SS_SYSID_xxx */ 364 int got_herc; /* Hercules chip present */ 365 int speed; /* SS_SPEED_xxx */ 366 int mode; /* SS_MODE_xxx */ 367 int verbose; /* Print a lot of status info. */ 368 int duration; /* Overall test duration in sec. */ 369 int interval; /* Interval to check counters */ 370 int pli; /* Packet length increment */ 371 } system_snake_opts_t; 372 373 typedef struct system_snake_info_s { 374 lb2s_port_connect_t snake_pi[SS_MAX_SNAKE][SS_MAX_SNAKE_CONN]; 375 lb2s_port_connect_t cmic_return_pi[SS_MAX_SNAKE]; 376 int install_count[SOC_MAX_NUM_DEVICES]; 377 loopback2_test_t lw[SOC_MAX_NUM_DEVICES]; 378 int num_packets[SOC_MAX_NUM_DEVICES]; 379 int io_unit[SOC_MAX_NUM_DEVICES]; 380 int io_unit_num; 381 lb2_port_stat_t *stats[SOC_MAX_NUM_DEVICES]; 382 } system_snake_info_t; 383 384 typedef struct system_snake_conn_s { 385 int unit; 386 int src_mod; 387 bcm_port_t src_port; 388 int dst_mod; 389 bcm_port_t dst_port; 390 unsigned int flags; 391 } system_snake_conn_t; 392 393 typedef struct system_snake_path_s { 394 int conn_count; 395 int packet_length_inc; 396 int return_unit; /* For ext, return unit may differ from tx unit */ 397 system_snake_conn_t conn[SS_MAX_SNAKE_CONN]; 398 } system_snake_path_t; 399 400 typedef struct system_snake_list_s { 401 int snake_port; 402 system_snake_path_t *snake_path; 403 } system_snake_list_t; 404 405 /* locals */ 406 static const char *ss_speed_str[SS_SPEED_NUM + 1] = { 407 "Default", /* SS_SPEED_DEFAULT */ 408 "MAXimum", /* SS_SPEED_MAX */ 409 "10fullduplex", /* SS_SPEED_10 */ 410 "100fullduplex", /* SS_SPEED_100 */ 411 "1000fullduplex", /* SS_SPEED_1000 */ 412 "2500fullduplex", /* SS_SPEED_2500 */ 413 "3000fullduplex", /* SS_SPEED_3000 */ 414 "10Gfullduplex", /* SS_SPEED_10G */ 415 NULL 416 }; 417 418 static int ss_speed_mbits[SS_SPEED_NUM] = { 419 0, /* Not used */ 420 0, /* Not used */ 421 10, /* 10Mbps */ 422 100, /* 100Mbps */ 423 1000, /* 1Gbps */ 424 2500, /* 2.5 Gbps */ 425 3000, /* 3.0 Gbps */ 426 10000 /* 10Gbps */ 427 }; 428 429 static int ss_speed_abil[SS_SPEED_NUM] = { 430 0, /* Not used */ 431 0, /* Not used */ 432 BCM_PORT_ABIL_10MB_FD, 433 BCM_PORT_ABIL_100MB_FD, 434 BCM_PORT_ABIL_1000MB_FD, 435 BCM_PORT_ABIL_2500MB_FD, 436 BCM_PORT_ABIL_3000MB_FD, 437 BCM_PORT_ABIL_10GB_FD 438 }; 439 440 441 static const char *ss_mode_str[SS_MODE_NUM + 1] = { 442 "MAC", /* SS_MODE_MAC */ 443 "PHY", /* SS_MODE_PHY */ 444 "EXT", /* SS_MODE_EXT */ 445 NULL 446 }; 447 448 static const char *ss_sysid_str[SS_SYSID_NUM + 1] = { 449 "firebolt", /* SS_SYSID_FIREBOLT */ 450 "fbpoe", /* SS_SYSID_FBPOE */ 451 "lmfb48", /* SS_SYSID_LM_FB48 */ 452 "felix48", /* SS_SYSID_LM_FELIX48P */ 453 "ics_eb", /* SS_SYSID_ICS_EB */ 454 "ge_hu_48p", /* SS_SYSID_GE_HU48 */ 455 "fe_hu_48p", /* SS_SYSID_FE_HU48 */ 456 NULL 457 }; 458 459 STATIC uint32 ss_unit_bitmap[SS_SYSID_NUM] = { 460 0x01, /* SS_SYSID_FIREBOLT */ 461 0x03, /* SS_SYSID_FBPOE */ 462 0x03, /* SS_SYSID_LM_FB48 */ 463 0x03, /* SS_SYSID_LM_FELIX48P */ 464 0x03, /* SS_SYSID_ICS_EB */ 465 0x03, /* SS_SYSID_GE_HU48 */ 466 0x03, /* SS_SYSID_FE_HU48 */ 467 }; 468 469 STATIC uint32 ss_num_paths[SS_SYSID_NUM] = { 470 28, /* SS_SYSID_FIREBOLT */ 471 28, /* SS_SYSID_FBPOE */ 472 24, /* SS_SYSID_LM_FB48 */ 473 27, /* SS_SYSID_LM_FELIX48P */ 474 26, /* SS_SYSID_ICS_EB */ 475 28, /* SS_SYSID_GE_HU48 */ 476 26, /* SS_SYSID_FE_HU48 */ 477 }; 478 479 STATIC char * ss_init_file[SS_SYSID_NUM] = { 480 NULL, /* SS_SYSID_FIREBOLT */ 481 SS_SOC_SCRIPT, /* SS_SYSID_FBPOE */ 482 SS_SOC_SCRIPT, /* SS_SYSID_LM_FB48 */ 483 NULL, /* SS_SYSID_LM_FELIX48P */ 484 SS_SOC_SCRIPT, /* SS_SYSID_ICS_EB */ 485 SS_SOC_SCRIPT, /* SS_SYSID_GE_HU48 */ 486 SS_SOC_SCRIPT, /* SS_SYSID_FE_HU48 */ 487 }; 488 489 STATIC sal_mac_addr_t ss_mac_src[SS_MAX_SNAKE] = { 490 {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, 491 {0x00, 0x11, 0x22, 0x33, 0x44, 0x66}, 492 {0x00, 0x11, 0x22, 0x33, 0x44, 0x77}, 493 {0x00, 0x11, 0x22, 0x33, 0x44, 0x88}, 494 {0x00, 0x11, 0x22, 0x33, 0x44, 0x99}, 495 {0x00, 0x11, 0x22, 0x33, 0x44, 0xaa}, 496 {0x00, 0x11, 0x22, 0x33, 0x44, 0xbb}, 497 {0x00, 0x11, 0x22, 0x33, 0x44, 0xcc}, 498 {0x00, 0x11, 0x22, 0x33, 0x44, 0xdd}, 499 {0x00, 0x11, 0x22, 0x33, 0x44, 0xee}, 500 {0x00, 0x11, 0x22, 0x33, 0x44, 0xff}, 501 {0x00, 0x11, 0x22, 0x33, 0x44, 0x00}, 502 {0x00, 0x11, 0x22, 0x33, 0x44, 0x11}, 503 {0x00, 0x11, 0x22, 0x33, 0x44, 0x12}, 504 {0x00, 0x11, 0x22, 0x33, 0x45, 0x55}, 505 {0x00, 0x11, 0x22, 0x33, 0x45, 0x66}, 506 {0x00, 0x11, 0x22, 0x33, 0x45, 0x77}, 507 {0x00, 0x11, 0x22, 0x33, 0x45, 0x88}, 508 {0x00, 0x11, 0x22, 0x33, 0x45, 0x99}, 509 {0x00, 0x11, 0x22, 0x33, 0x45, 0xaa}, 510 {0x00, 0x11, 0x22, 0x33, 0x45, 0xbb}, 511 {0x00, 0x11, 0x22, 0x33, 0x45, 0xcc}, 512 {0x00, 0x11, 0x22, 0x33, 0x45, 0xdd}, 513 {0x00, 0x11, 0x22, 0x33, 0x45, 0xee}, 514 {0x00, 0x11, 0x22, 0x33, 0x45, 0xff}, 515 {0x00, 0x11, 0x22, 0x33, 0x45, 0x00}, 516 {0x00, 0x11, 0x22, 0x33, 0x45, 0x11}, 517 {0x00, 0x11, 0x22, 0x33, 0x45, 0x12}, 518 }; 519 520 STATIC sal_mac_addr_t ss_mac_dst[SS_MAX_SNAKE] = { 521 {0x66, 0x77, 0x88, 0x99, 0xaa, 0xff}, 522 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x00}, 523 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x11}, 524 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x22}, 525 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x33}, 526 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x44}, 527 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x55}, 528 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x66}, 529 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x77}, 530 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x88}, 531 {0x66, 0x77, 0x88, 0x99, 0xaa, 0x99}, 532 {0x66, 0x77, 0x88, 0x99, 0xaa, 0xaa}, 533 {0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb}, 534 {0x66, 0x77, 0x88, 0x99, 0xaa, 0xcc}, 535 {0x66, 0x77, 0x88, 0x99, 0xab, 0xff}, 536 {0x66, 0x77, 0x88, 0x99, 0xab, 0x00}, 537 {0x66, 0x77, 0x88, 0x99, 0xab, 0x11}, 538 {0x66, 0x77, 0x88, 0x99, 0xab, 0x22}, 539 {0x66, 0x77, 0x88, 0x99, 0xab, 0x33}, 540 {0x66, 0x77, 0x88, 0x99, 0xab, 0x44}, 541 {0x66, 0x77, 0x88, 0x99, 0xab, 0x55}, 542 {0x66, 0x77, 0x88, 0x99, 0xab, 0x66}, 543 {0x66, 0x77, 0x88, 0x99, 0xab, 0x77}, 544 {0x66, 0x77, 0x88, 0x99, 0xab, 0x88}, 545 {0x66, 0x77, 0x88, 0x99, 0xab, 0x99}, 546 {0x66, 0x77, 0x88, 0x99, 0xab, 0xaa}, 547 {0x66, 0x77, 0x88, 0x99, 0xab, 0xbb}, 548 {0x66, 0x77, 0x88, 0x99, 0xab, 0xcc}, 549 }; 550 551 552 /* 553 * Snake descriptions per board 554 */ 555 556 /* 557 * Firebolt uses 28 snakes, one per GE/XE port on 56504. 558 */ 559 560 STATIC system_snake_path_t firebolt_snake_cw = { 561 1, 562 480, 563 0, 564 { /* u sm sp dm dp flags */ 565 { 0, 0, 0, 0, 0, SS_DP_PATH | SS_DP_FORCE }, 566 } 567 }; 568 569 STATIC system_snake_list_t firebolt_snake_test[] = { 570 { 0, &firebolt_snake_cw }, 571 { 1, &firebolt_snake_cw }, 572 { 2, &firebolt_snake_cw }, 573 { 3, &firebolt_snake_cw }, 574 { 4, &firebolt_snake_cw }, 575 { 5, &firebolt_snake_cw }, 576 { 6, &firebolt_snake_cw }, 577 { 7, &firebolt_snake_cw }, 578 { 8, &firebolt_snake_cw }, 579 { 9, &firebolt_snake_cw }, 580 { 10, &firebolt_snake_cw }, 581 { 11, &firebolt_snake_cw }, 582 { 12, &firebolt_snake_cw }, 583 { 13, &firebolt_snake_cw }, 584 { 14, &firebolt_snake_cw }, 585 { 15, &firebolt_snake_cw }, 586 { 16, &firebolt_snake_cw }, 587 { 17, &firebolt_snake_cw }, 588 { 18, &firebolt_snake_cw }, 589 { 19, &firebolt_snake_cw }, 590 { 20, &firebolt_snake_cw }, 591 { 21, &firebolt_snake_cw }, 592 { 22, &firebolt_snake_cw }, 593 { 23, &firebolt_snake_cw }, 594 { 24, &firebolt_snake_cw }, 595 { 25, &firebolt_snake_cw }, 596 { 26, &firebolt_snake_cw }, 597 { 27, &firebolt_snake_cw }, 598 }; 599 600 /* 601 * POE uses 2 snakes, one per GE port on 56504. 602 * For even port numbers they go clockwise and for odd port 603 * numbers they go counter-clockwise. Also there are 4 snakes 604 * one each XGE0-1 port on each device. 605 */ 606 STATIC system_snake_path_t fbpoe_snake_cw = { 607 2, 608 183, 609 0, 610 { /* u sm sp dm dp flags */ 611 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 612 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 613 } 614 }; 615 616 STATIC system_snake_path_t fbpoe_snake_ccw = { 617 2, 618 183, 619 0, 620 { /* u sm sp dm dp flags */ 621 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 622 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 623 } 624 }; 625 626 STATIC system_snake_path_t fbpoe_10ge_u0_snake_cw = { 627 1, 628 480, 629 0, 630 { /* u sm sp dm dp flags */ 631 { 0, 0, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 632 } 633 }; 634 635 STATIC system_snake_path_t fbpoe_10ge_u1_snake_cw = { 636 1, 637 480, 638 1, 639 { /* u sm sp dm dp flags */ 640 { 1, 1, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 641 } 642 }; 643 644 STATIC system_snake_list_t fbpoe_snake_test[] = { 645 { 0, &fbpoe_snake_cw }, 646 { 1, &fbpoe_snake_ccw }, 647 { 2, &fbpoe_snake_cw }, 648 { 3, &fbpoe_snake_ccw }, 649 { 4, &fbpoe_snake_cw }, 650 { 5, &fbpoe_snake_ccw }, 651 { 6, &fbpoe_snake_cw }, 652 { 7, &fbpoe_snake_ccw }, 653 { 8, &fbpoe_snake_cw }, 654 { 9, &fbpoe_snake_ccw }, 655 { 10, &fbpoe_snake_cw }, 656 { 11, &fbpoe_snake_ccw }, 657 { 12, &fbpoe_snake_cw }, 658 { 13, &fbpoe_snake_ccw }, 659 { 14, &fbpoe_snake_cw }, 660 { 15, &fbpoe_snake_ccw }, 661 { 16, &fbpoe_snake_cw }, 662 { 17, &fbpoe_snake_ccw }, 663 { 18, &fbpoe_snake_cw }, 664 { 19, &fbpoe_snake_ccw }, 665 { 20, &fbpoe_snake_cw }, 666 { 21, &fbpoe_snake_ccw }, 667 { 22, &fbpoe_snake_cw }, 668 { 23, &fbpoe_snake_ccw }, 669 { 24, &fbpoe_10ge_u0_snake_cw }, 670 { 25, &fbpoe_10ge_u0_snake_cw }, 671 { 24, &fbpoe_10ge_u1_snake_cw }, 672 { 25, &fbpoe_10ge_u1_snake_cw }, 673 }; 674 675 /* 676 * LM_FB48 uses 2 snakes, one per GE port on 56504. 677 * For even port numbers they go clockwise and for odd port 678 * numbers they go counter-clockwise. 679 */ 680 STATIC system_snake_path_t lm_fb48_snake_cw = { 681 2, 682 183, 683 0, 684 { /* u sm sp dm dp flags */ 685 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 686 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 687 } 688 }; 689 690 STATIC system_snake_path_t lm_fb48_snake_ccw = { 691 2, 692 183, 693 0, 694 { /* u sm sp dm dp flags */ 695 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 696 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 697 } 698 }; 699 700 STATIC system_snake_list_t lmfb48_snake_test[] = { 701 { 0, &lm_fb48_snake_cw }, 702 { 1, &lm_fb48_snake_ccw }, 703 { 2, &lm_fb48_snake_cw }, 704 { 3, &lm_fb48_snake_ccw }, 705 { 4, &lm_fb48_snake_cw }, 706 { 5, &lm_fb48_snake_ccw }, 707 { 6, &lm_fb48_snake_cw }, 708 { 7, &lm_fb48_snake_ccw }, 709 { 8, &lm_fb48_snake_cw }, 710 { 9, &lm_fb48_snake_ccw }, 711 { 10, &lm_fb48_snake_cw }, 712 { 11, &lm_fb48_snake_ccw }, 713 { 12, &lm_fb48_snake_cw }, 714 { 13, &lm_fb48_snake_ccw }, 715 { 14, &lm_fb48_snake_cw }, 716 { 15, &lm_fb48_snake_ccw }, 717 { 16, &lm_fb48_snake_cw }, 718 { 17, &lm_fb48_snake_ccw }, 719 { 18, &lm_fb48_snake_cw }, 720 { 19, &lm_fb48_snake_ccw }, 721 { 20, &lm_fb48_snake_cw }, 722 { 21, &lm_fb48_snake_ccw }, 723 { 22, &lm_fb48_snake_cw }, 724 { 23, &lm_fb48_snake_ccw }, 725 }; 726 727 /* 728 * Felix 48 port uses 2 snakes per port. The platform has 2 729 * felix devices (24 FE, 1 GE and 1 10GE port). The 2 devices are 730 * connected through HG0 port. 731 */ 732 STATIC system_snake_path_t felix48p_snake_cw = { 733 2, 734 483, 735 0, 736 { /* u sm sp dm dp flags */ 737 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 738 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 739 } 740 }; 741 742 STATIC system_snake_path_t felix48p_snake_ccw = { 743 2, 744 483, 745 0, 746 { /* u sm sp dm dp flags */ 747 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 748 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 749 } 750 }; 751 752 STATIC system_snake_path_t felix48p_snake_ge_cw = { 753 2, 754 183, 755 0, 756 { /* u sm sp dm dp flags */ 757 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 758 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 759 } 760 }; 761 762 STATIC system_snake_path_t felix48p_snake_ge_ccw = { 763 2, 764 183, 765 0, 766 { /* u sm sp dm dp flags */ 767 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 768 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 769 } 770 }; 771 772 STATIC system_snake_path_t felix48p_10ge_snake_cw = { 773 2, 774 480, 775 0, 776 { /* u sm sp dm dp flags */ 777 { 0, 0, 27, 1, 27, SS_DP_NOEXT }, 778 { 1, 1, 27, 0, 27, SS_DP_NOEXT }, 779 } 780 }; 781 782 STATIC system_snake_list_t felix48p_snake_test[] = { 783 { 0, &felix48p_snake_cw }, 784 { 1, &felix48p_snake_ccw }, 785 { 2, &felix48p_snake_cw }, 786 { 3, &felix48p_snake_ccw }, 787 { 4, &felix48p_snake_cw }, 788 { 5, &felix48p_snake_ccw }, 789 { 6, &felix48p_snake_cw }, 790 { 7, &felix48p_snake_ccw }, 791 { 8, &felix48p_snake_cw }, 792 { 9, &felix48p_snake_ccw }, 793 { 10, &felix48p_snake_cw }, 794 { 11, &felix48p_snake_ccw }, 795 { 12, &felix48p_snake_cw }, 796 { 13, &felix48p_snake_ccw }, 797 { 14, &felix48p_snake_cw }, 798 { 15, &felix48p_snake_ccw }, 799 { 16, &felix48p_snake_cw }, 800 { 17, &felix48p_snake_ccw }, 801 { 18, &felix48p_snake_cw }, 802 { 19, &felix48p_snake_ccw }, 803 { 20, &felix48p_snake_cw }, 804 { 21, &felix48p_snake_ccw }, 805 { 22, &felix48p_snake_cw }, 806 { 23, &felix48p_snake_ccw }, 807 { 24, &felix48p_snake_ge_cw }, 808 { 25, &felix48p_snake_ge_ccw }, 809 { 27, &felix48p_10ge_snake_cw }, 810 }; 811 812 /* 813 * Raptor/Raven cascase platform with slave connected over EB bus. 814 * special config setting needed ss_ignore_pbmp=0x3e so that we 815 * dont mess around with the link ports as eb slave depends on that. 816 */ 817 818 STATIC system_snake_path_t raptor_eb_snake_cw = { 819 2, 820 483, 821 0, 822 { /* u sm sp dm dp flags */ 823 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 824 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 825 } 826 }; 827 828 STATIC system_snake_path_t raptor_eb_ge1_snake_cw = { 829 2, 830 1600, 831 1, 832 { /* u sm sp dm dp flags */ 833 { 0, 0, 2, 1, 2, SS_DP_NOEXT }, 834 { 1, 1, 2, 0, 2, SS_DP_NOEXT }, 835 } 836 }; 837 STATIC system_snake_path_t raptor_eb_ge4_snake_cw = { 838 2, 839 1600, 840 1, 841 { /* u sm sp dm dp flags */ 842 { 0, 0, 5, 1, 5, SS_DP_NOEXT }, 843 { 1, 1, 5, 0, 5, SS_DP_NOEXT }, 844 } 845 }; 846 847 STATIC system_snake_list_t raptor_eb_snake_test[] = { 848 { 6, &raptor_eb_snake_cw }, 849 { 7, &raptor_eb_snake_cw }, 850 { 8, &raptor_eb_snake_cw }, 851 { 9, &raptor_eb_snake_cw }, 852 { 10, &raptor_eb_snake_cw }, 853 { 11, &raptor_eb_snake_cw }, 854 { 12, &raptor_eb_snake_cw }, 855 { 13, &raptor_eb_snake_cw }, 856 { 14, &raptor_eb_snake_cw }, 857 { 15, &raptor_eb_snake_cw }, 858 { 16, &raptor_eb_snake_cw }, 859 { 17, &raptor_eb_snake_cw }, 860 { 18, &raptor_eb_snake_cw }, 861 { 19, &raptor_eb_snake_cw }, 862 { 20, &raptor_eb_snake_cw }, 863 { 21, &raptor_eb_snake_cw }, 864 { 22, &raptor_eb_snake_cw }, 865 { 23, &raptor_eb_snake_cw }, 866 { 24, &raptor_eb_snake_cw }, 867 { 25, &raptor_eb_snake_cw }, 868 { 26, &raptor_eb_snake_cw }, 869 { 27, &raptor_eb_snake_cw }, 870 { 28, &raptor_eb_snake_cw }, 871 { 29, &raptor_eb_snake_cw }, 872 { 2, &raptor_eb_ge1_snake_cw }, 873 { 5, &raptor_eb_ge4_snake_cw }, 874 }; 875 876 /* 877 * In Hurricane, Port 1 is reserved port.. 878 * Hu uses 2 ports per snake - one per unit. 879 * even ports go clockwise and odd ports counterclockwise 880 * Ext snake uses one cw and one ccw 881 * for SFP ports, In unit0 it is 26 & 27, in Unit 1 it is 28 & 29 882 */ 883 STATIC system_snake_path_t hu_48p_snake_cw = { 884 2, 885 183, 886 0, 887 { /* u sm sp dm dp flags */ 888 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 889 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 890 } 891 }; 892 893 STATIC system_snake_path_t hu_48p_snake_ccw = { 894 2, 895 183, 896 0, 897 { /* u sm sp dm dp flags */ 898 { 1, 1, 0, 0, 0, SS_SP_PATH | SS_DP_PATH }, 899 { 0, 0, 0, 1, 0, SS_SP_PATH | SS_DP_PATH }, 900 } 901 }; 902 903 STATIC system_snake_path_t hu_48p_snake_u0 = { 904 1, 905 183, 906 0, 907 { /* u sm sp dm dp flags */ 908 { 0, 0, 0, 0, 0, SS_SP_PATH | SS_DP_PATH}, 909 } 910 }; 911 912 STATIC system_snake_path_t hu_48p_snake_u1 = { 913 1, 914 183, 915 1, 916 { /* u sm sp dm dp flags */ 917 { 1, 1, 0, 1, 0, SS_SP_PATH | SS_DP_PATH}, 918 } 919 }; 920 921 STATIC system_snake_list_t hurricane_ge_48p_snake_test[] = { 922 { 2, &hu_48p_snake_cw }, 923 { 3, &hu_48p_snake_ccw }, 924 { 4, &hu_48p_snake_cw }, 925 { 5, &hu_48p_snake_ccw }, 926 { 6, &hu_48p_snake_cw }, 927 { 7, &hu_48p_snake_ccw }, 928 { 8, &hu_48p_snake_cw }, 929 { 9, &hu_48p_snake_ccw }, 930 { 10, &hu_48p_snake_cw }, 931 { 11, &hu_48p_snake_ccw }, 932 { 12, &hu_48p_snake_cw }, 933 { 13, &hu_48p_snake_ccw }, 934 { 14, &hu_48p_snake_cw }, 935 { 15, &hu_48p_snake_ccw }, 936 { 16, &hu_48p_snake_cw }, 937 { 17, &hu_48p_snake_ccw }, 938 { 18, &hu_48p_snake_cw }, 939 { 19, &hu_48p_snake_ccw }, 940 { 20, &hu_48p_snake_cw }, 941 { 21, &hu_48p_snake_ccw }, 942 { 22, &hu_48p_snake_cw }, 943 { 23, &hu_48p_snake_ccw }, 944 { 24, &hu_48p_snake_cw }, 945 { 25, &hu_48p_snake_ccw }, 946 { 26, &hu_48p_snake_u1 }, 947 { 27, &hu_48p_snake_u1 }, 948 { 28, &hu_48p_snake_u0 }, 949 { 29, &hu_48p_snake_u0 }, 950 }; 951 952 STATIC system_snake_list_t hurricane_fe_48p_snake_test[] = { 953 { 2, &hu_48p_snake_cw }, 954 { 3, &hu_48p_snake_ccw }, 955 { 4, &hu_48p_snake_cw }, 956 { 5, &hu_48p_snake_ccw }, 957 { 6, &hu_48p_snake_cw }, 958 { 7, &hu_48p_snake_ccw }, 959 { 8, &hu_48p_snake_cw }, 960 { 9, &hu_48p_snake_ccw }, 961 { 10, &hu_48p_snake_cw }, 962 { 11, &hu_48p_snake_ccw }, 963 { 12, &hu_48p_snake_cw }, 964 { 13, &hu_48p_snake_ccw }, 965 { 14, &hu_48p_snake_cw }, 966 { 15, &hu_48p_snake_ccw }, 967 { 16, &hu_48p_snake_cw }, 968 { 17, &hu_48p_snake_ccw }, 969 { 18, &hu_48p_snake_cw }, 970 { 19, &hu_48p_snake_ccw }, 971 { 20, &hu_48p_snake_cw }, 972 { 21, &hu_48p_snake_ccw }, 973 { 22, &hu_48p_snake_cw }, 974 { 23, &hu_48p_snake_ccw }, 975 { 24, &hu_48p_snake_cw }, 976 { 25, &hu_48p_snake_ccw }, 977 { 26, &hu_48p_snake_u1 }, 978 { 27, &hu_48p_snake_u1 }, 979 }; 980 981 /* 982 * Finally, all boards together 983 */ 984 STATIC system_snake_list_t *ss_snake_table[SS_SYSID_NUM] = { 985 firebolt_snake_test, 986 fbpoe_snake_test, 987 lmfb48_snake_test, 988 felix48p_snake_test, 989 raptor_eb_snake_test, 990 hurricane_ge_48p_snake_test, 991 hurricane_fe_48p_snake_test, 992 }; 993 994 995 STATIC system_snake_info_t ssi; 996 997 STATIC bcm_port_config_t pcfg[SOC_MAX_NUM_DEVICES]; 998 999 STATIC int 1000 ss_unit_setup(system_snake_opts_t *opts, int unit) 1001 { 1002 int rv; 1003 bcm_port_t port, dport; 1004 bcm_pbmp_t vlan_pbm; 1005 bcm_vlan_t vlan; 1006 pbmp_t ss_pbm, ignore_pbm; 1007 1008 if (opts->verbose) { 1009 cli_out("Configuring Ethernet ports on unit %d (%s)\n", 1010 unit, SOC_UNIT_NAME(unit)); 1011 } 1012 1013 if (bcm_port_config_get(unit, &pcfg[unit]) != BCM_E_NONE) { 1014 cli_out("Error: bcm ports not initialized\n"); 1015 return (-1); 1016 } 1017 1018 if ((rv = bcm_vlan_destroy_all(unit)) < 0) { 1019 cli_out("Could not destroy existing VLANs: %s\n", 1020 bcm_errmsg(rv)); 1021 return (-1); 1022 } 1023 1024 BCM_PBMP_ASSIGN(vlan_pbm, pcfg[unit].all); 1025 ss_pbm = pcfg[unit].e; 1026 if (soc_property_get_str(unit, spn_SS_IGNORE_PBMP)) { 1027 ignore_pbm = soc_property_get_bcm_pbmp(unit, spn_SS_IGNORE_PBMP, 0); 1028 BCM_PBMP_REMOVE(ss_pbm, ignore_pbm); 1029 cli_out("Removed ignore_pbm from valid ports \n"); 1030 } 1031 DPORT_BCM_PBMP_ITER(unit, ss_pbm, dport, port) { 1032 if (opts->verbose) { 1033 cli_out("\tConfiguring port %s\n", BCM_PORT_NAME(unit, port)); 1034 } 1035 1036 /* Note Ingress Etherport # = path # for now */ 1037 vlan = SS_VLAN_BASE + port; 1038 if (((rv = bcm_vlan_create(unit, vlan)) < 0) && 1039 (rv != BCM_E_EXISTS) ) { 1040 test_error(unit, 1041 "Could not create VLAN %d: %s\n", 1042 vlan, bcm_errmsg(rv)); 1043 return (-1); 1044 } 1045 1046 if ((rv = bcm_vlan_port_add(unit, vlan, vlan_pbm, vlan_pbm)) < 0) { 1047 test_error(unit, 1048 "Could not add test ports to VLAN %d: %s\n", 1049 vlan, bcm_errmsg(rv)); 1050 return (-1); 1051 } 1052 1053 if ((rv = bcm_port_untagged_vlan_set(unit, port, vlan)) < 0) { 1054 test_error(unit, 1055 "Could not set port %s to tag with VLAN %d: %s\n", 1056 BCM_PORT_NAME(unit, port), vlan, bcm_errmsg(rv)); 1057 return (-1); 1058 } 1059 1060 if (opts->mode == SS_MODE_MAC) { 1061 if ((rv = bcm_port_loopback_set(unit, port, 1062 BCM_PORT_LOOPBACK_MAC)) < 0) { 1063 test_error(unit, 1064 "Port %s: Failed to set MAC loopback: %s\n", 1065 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1066 return(-1); /* In case they continue */ 1067 } 1068 } else if (opts->mode == SS_MODE_PHY) { 1069 if ((rv = bcm_port_loopback_set(unit, port, 1070 BCM_PORT_LOOPBACK_PHY)) < 0) { 1071 test_error(unit, 1072 "Port %s: Failed to set PHY loopback: %s\n", 1073 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1074 return(-1); /* In case they continue */ 1075 } 1076 } else { 1077 /* Else normal port operation for SS_MODE_EXT, where */ 1078 /* ports are wired 1-2, 3-4, 5-6 etc. */ 1079 1080 assert(opts->mode == SS_MODE_EXT); 1081 } 1082 1083 if ((rv = bcm_port_enable_set(unit, port, TRUE)) < 0) { 1084 test_error(unit, 1085 "Port %s: Failed to enable ports: %s\n", 1086 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1087 return(-1); /* In case they continue */ 1088 } 1089 1090 if ((rv = bcm_port_learn_set(unit, port, 1091 BCM_PORT_LEARN_FWD)) < 0) { 1092 test_error(unit, 1093 "Unable to set learn state: port %s: %s\n", 1094 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1095 return (-1); 1096 } 1097 1098 /* Use speed set by rc unless overridden on cmd line. */ 1099 if (!BCM_PBMP_MEMBER(pcfg[unit].xe, port)) { 1100 int speed = ss_speed_mbits[opts->speed]; 1101 1102 if (opts->speed == SS_SPEED_DEFAULT) { 1103 if ((rv = bcm_port_speed_max(unit, port, &speed)) < 0) { 1104 test_error(unit, 1105 "Port %s: Failed to get max port speed: %s\n", 1106 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1107 return(-1); /* In case they continue */ 1108 } 1109 } 1110 1111 /* 1112 * Set speed in any case. Otherwise, the internal PHY/MAC 1113 * will not necessarily be programmed correctly since linkscan 1114 * is no longer scanning the port after it is in loopback. 1115 */ 1116 if ((rv = bcm_port_speed_set(unit, port, speed)) < 0) { 1117 test_error(unit, 1118 "Port %s: Failed to set port speed: %s\n", 1119 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1120 return(-1); /* In case they continue */ 1121 } 1122 } 1123 1124 /* Always use full duplex for ss. */ 1125 if ((rv = bcm_port_duplex_set(unit, port, 1126 BCM_PORT_DUPLEX_FULL)) < 0) { 1127 test_error(unit, 1128 "Port %s: Failed to set port duplex: %s\n", 1129 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1130 return(-1); /* In case they continue */ 1131 } 1132 1133 if (opts->mode == SS_MODE_EXT) { 1134 /* Always use full duplex for ss. */ 1135 if ((rv = bcm_port_advert_set(unit, port, 1136 BCM_PORT_ABIL_FD)) < 0) { 1137 test_error(unit, 1138 "Port %s: Failed to set port duplex advert: %s\n", 1139 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1140 return(-1); /* In case they continue */ 1141 } 1142 if (opts->speed != SS_SPEED_DEFAULT) { 1143 /* Use cmd line speed */ 1144 if ((rv = 1145 bcm_port_advert_set(unit, port, 1146 ss_speed_abil[opts->speed])) < 0) { 1147 test_error(unit, 1148 "Port %s: " 1149 "Failed to set port speed advert: %s\n", 1150 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1151 return(-1); /* In case they continue */ 1152 } 1153 } 1154 /* Restart autonegotiation */ 1155 if ((rv = bcm_port_autoneg_set(unit, port, 1156 TRUE)) < 0) { 1157 test_error(unit, 1158 "Port %s: Failed to restart autonegotiation: %s\n", 1159 BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 1160 return(-1); /* In case they continue */ 1161 } 1162 } /* SS_MODE_EXT advert and autoneg */ 1163 1164 } /* For each port */ 1165 1166 return (0); 1167 } 1168 1169 STATIC void 1170 ss_set_packet_length_increment(system_snake_opts_t *opts) 1171 { 1172 int snake; 1173 int sysid = opts->sysid; 1174 int snake_num = ss_num_paths[sysid]; 1175 system_snake_list_t *snake_list = ss_snake_table[sysid]; 1176 1177 for (snake = 0; snake < snake_num; snake++) { 1178 snake_list[snake].snake_path->packet_length_inc = opts->pli; 1179 } 1180 } 1181 1182 STATIC int 1183 ss_port_interconnect_define(system_snake_opts_t *opts) 1184 { 1185 lb2s_port_connect_t *pi; 1186 int snake; 1187 system_snake_list_t *snake_list; 1188 system_snake_path_t *snake_path; 1189 int snake_num; 1190 int snake_len; 1191 int snake_port; 1192 int i; 1193 int sysid = opts->sysid; 1194 1195 snake_list = ss_snake_table[sysid]; 1196 snake_num = ss_num_paths[sysid]; 1197 1198 for (snake = 0; snake < snake_num; snake++) { 1199 /* 1200 * Define snake interconnects 1201 */ 1202 if (opts->verbose) { 1203 cli_out("Setting up snake %d\n", snake); 1204 } 1205 1206 snake_path = snake_list[snake].snake_path; 1207 snake_port = snake_list[snake].snake_port; 1208 snake_len = snake_path->conn_count; 1209 1210 for (i = 0; i < snake_len; i++) { 1211 pi = &ssi.snake_pi[snake][i]; 1212 sal_memset(pi, 0, sizeof(*pi)); 1213 1214 pi->src_modid = snake_path->conn[i].src_mod; 1215 pi->this_port = snake_path->conn[i].src_port; 1216 pi->dst_modid = snake_path->conn[i].dst_mod; 1217 pi->to_port = snake_path->conn[i].dst_port; 1218 pi->added_vlan = SS_VLAN_BASE + snake_port; 1219 ENET_SET_MACADDR(pi->src_mac, ss_mac_src[snake]); 1220 ENET_SET_MACADDR(pi->dst_mac, ss_mac_dst[snake]); 1221 1222 if (snake_path->conn[i].flags & SS_SM_PATH) { 1223 pi->src_modid += snake_port; 1224 } 1225 1226 if (snake_path->conn[i].flags & SS_SP_PATH) { 1227 pi->this_port += snake_port; 1228 } 1229 1230 if (snake_path->conn[i].flags & SS_DM_PATH) { 1231 pi->dst_modid += snake_port; 1232 } 1233 1234 if (snake_path->conn[i].flags & SS_DP_PATH) { 1235 pi->to_port += snake_port; 1236 if ((opts->mode == SS_MODE_EXT) || 1237 (snake_path->conn[i].flags & SS_DP_FORCE)) { 1238 if (!(snake_path->conn[i].flags & SS_DP_NOEXT)) { 1239 pi->to_port ^= 1; 1240 } 1241 } 1242 } 1243 1244 pi->valid_info = TRUE; 1245 1246 if (opts->verbose) { 1247 cli_out("\t%02d.%02d -> %02d.%02d\n", 1248 pi->src_modid, pi->this_port, 1249 pi->dst_modid, pi->to_port); 1250 } 1251 } 1252 1253 /* 1254 * Define the CPU return path (for each snake it is the first unit 1255 * in snake's definition that is used for cell injection and return) 1256 */ 1257 pi = &ssi.cmic_return_pi[snake]; 1258 sal_memset(pi, 0, sizeof(*pi)); 1259 1260 pi->src_modid = snake_path->conn[0].src_mod; 1261 pi->this_port = snake_port; 1262 pi->dst_modid = snake_path->conn[0].src_mod; 1263 pi->to_port = CMIC_PORT(snake_path->conn[0].unit); 1264 pi->added_vlan = SS_VLAN_BASE + snake_port; 1265 ENET_SET_MACADDR(pi->src_mac, ss_mac_src[snake]); 1266 ENET_SET_MACADDR(pi->dst_mac, ss_mac_dst[snake]); 1267 pi->valid_info = TRUE; 1268 1269 if (opts->verbose) { 1270 cli_out("\tReturn path via unit %d\n", snake_path->conn[0].unit); 1271 } 1272 } 1273 1274 return (0); 1275 } 1276 1277 STATIC int 1278 ss_port_interconnect_execute(system_snake_opts_t *opts) 1279 { 1280 lb2s_port_connect_t *pi; 1281 int snake; 1282 int snake_len; 1283 system_snake_path_t *snake_path; 1284 int i; 1285 int rv; 1286 int unit = 0; 1287 int sysid = opts->sysid; 1288 system_snake_list_t *snake_list = ss_snake_table[sysid]; 1289 int snake_num = ss_num_paths[sysid]; 1290 1291 for (snake = 0; snake < snake_num; snake++) { 1292 if (opts->verbose) { 1293 cli_out("Executing connections for snake %d\n", snake); 1294 } 1295 1296 snake_path = snake_list[snake].snake_path; 1297 snake_len = snake_path->conn_count; 1298 1299 for (i = 0; i < snake_len; i++) { 1300 unit = snake_path->conn[i].unit; 1301 pi = &ssi.snake_pi[snake][i]; 1302 1303 if (opts->verbose) { 1304 cli_out("\t%02d.%02d(%02d) -> %02d.%02d\n", 1305 pi->src_modid, pi->this_port, 1306 pi->added_vlan - SS_VLAN_BASE, 1307 pi->dst_modid, pi->to_port); 1308 } 1309 1310 rv = lbu_connect_ports(unit, pi, TRUE); 1311 if (rv < 0) { 1312 test_error(unit, 1313 "Port %s: Failed to connect to %02d.%02d: %s\n", 1314 BCM_PORT_NAME(unit, pi->this_port), 1315 pi->dst_modid, pi->to_port, bcm_errmsg(rv)); 1316 return (-1); 1317 } 1318 } 1319 } 1320 1321 return (0); 1322 } 1323 1324 STATIC void 1325 ss_io_units_find(system_snake_opts_t *opts) 1326 { 1327 int unit; 1328 int snake; 1329 system_snake_path_t *snake_path; 1330 int num_packets; 1331 int sysid = opts->sysid; 1332 system_snake_list_t *snake_list = ss_snake_table[sysid]; 1333 int snake_num = ss_num_paths[sysid]; 1334 1335 SS_UNIT_ITER(sysid, unit) { 1336 num_packets = 0; 1337 for (snake = 0; snake < snake_num; snake++) { 1338 snake_path = snake_list[snake].snake_path; 1339 /* Check if the snakes originates at the given unit */ 1340 if (snake_path->conn[0].unit == unit) { 1341 num_packets += SS_PACKETS_PER_PATH(snake_path); 1342 } 1343 } 1344 1345 ssi.num_packets[unit] = num_packets; 1346 1347 if (num_packets == 0) { 1348 continue; 1349 } 1350 1351 ssi.io_unit[ssi.io_unit_num++] = unit; 1352 } 1353 1354 if (opts->verbose) { 1355 cli_out("%d units found\n", ssi.io_unit_num); 1356 } 1357 } 1358 1359 STATIC int 1360 ss_packet_alloc(system_snake_opts_t *opts, int unit) 1361 { 1362 int num_packets = ssi.num_packets[unit]; 1363 1364 /* Allocate packet space */ 1365 1366 if (opts->verbose) { 1367 cli_out("%d Tx packets for unit %d\n", num_packets, unit); 1368 } 1369 1370 bcm_pkt_blk_alloc(unit, num_packets,SS_PACKET_LENGTH_MAX, 1371 BCM_TX_CRC_REGEN, &ssi.lw[unit].tx_pkts); 1372 if (!ssi.lw[unit].tx_pkts) { 1373 cli_out("Unable to allocate tx packet memory\n"); 1374 return BCM_E_MEMORY; 1375 } 1376 1377 if (opts->verbose) { 1378 cli_out("%d Rx packets for unit %d\n", num_packets, unit); 1379 } 1380 1381 ssi.lw[unit].rx_pkts = sal_alloc(num_packets * sizeof(bcm_pkt_t), 1382 "SS rx pkts"); 1383 if (!ssi.lw[unit].rx_pkts) { 1384 bcm_pkt_blk_free(unit, ssi.lw[unit].tx_pkts, num_packets); 1385 cli_out("Unable to allocate rx packet memory\n"); 1386 return BCM_E_MEMORY; 1387 } 1388 1389 sal_memset(ssi.lw[unit].rx_pkts, 0, num_packets * sizeof(bcm_pkt_t)); 1390 1391 if (opts->verbose) { 1392 cli_out("%d Tx packet match markers for unit %d\n", num_packets, unit); 1393 } 1394 1395 ssi.lw[unit].tx_pkt_match = sal_alloc(num_packets * sizeof(int), 1396 "SS TX match markers"); 1397 if (!ssi.lw[unit].tx_pkt_match) { 1398 bcm_pkt_blk_free(unit, ssi.lw[unit].tx_pkts, num_packets); 1399 sal_free(ssi.lw[unit].rx_pkts); 1400 return BCM_E_MEMORY; 1401 } 1402 1403 sal_memset(ssi.lw[unit].tx_pkt_match, 0, num_packets * sizeof(int)); 1404 1405 return (0); 1406 } 1407 1408 STATIC void 1409 ss_tx_packet_fill(system_snake_opts_t *opts, int unit) 1410 { 1411 int snake; 1412 lb2s_port_connect_t *pi; 1413 int length; 1414 int cur_offset; 1415 uint8 *sequence_p; 1416 bcm_pkt_t *pkt; 1417 enet_hdr_t *eh; 1418 int pkt_idx = 0; 1419 uint8 seq_no = SS_SEQUENCE_BASE; 1420 uint32 pattern = SS_PATTERN_BASE; 1421 int sysid = opts->sysid; 1422 system_snake_list_t *snake_list = ss_snake_table[sysid]; 1423 int snake_num = ss_num_paths[sysid]; 1424 1425 for (snake = 0; snake < snake_num; snake++) { 1426 if (snake_list[snake].snake_path->conn[0].unit != unit) { 1427 continue; 1428 } 1429 pi = &(ssi.snake_pi[snake][0]); 1430 for (length = SS_PACKET_LENGTH_MIN; length <= SS_PACKET_LENGTH_MAX; 1431 length += snake_list[snake].snake_path->packet_length_inc) { 1432 pkt = ssi.lw[unit].tx_pkts[pkt_idx]; 1433 pkt->cos = SS_COS; 1434 /* For now, internal priority matches COS (or v.v.) */ 1435 pkt->prio_int = SS_COS; 1436 pkt->opcode = BCM_HG_OPCODE_UC; 1437 pkt->pkt_data[0].len = length; 1438 BCM_PBMP_CLEAR(pkt->tx_pbmp); 1439 BCM_PBMP_PORT_ADD(pkt->tx_pbmp, pi->to_port); 1440 BCM_PBMP_CLEAR(pkt->tx_upbmp); 1441 BCM_PBMP_PORT_ADD(pkt->tx_upbmp, pi->to_port); 1442 1443 eh = (enet_hdr_t *)BCM_PKT_DMAC(pkt); 1444 1445 /* Write source/destination MAC address */ 1446 ENET_SET_MACADDR(&eh->en_dhost, pi->dst_mac); 1447 ENET_SET_MACADDR(&eh->en_shost, pi->src_mac); 1448 1449 /* Write VLAN tag (16 + 16 bits) and sequence number (32 bits) */ 1450 packet_store((uint8 *)&eh->en_tag_tpid, 2, 0x8100 << 16, 0); 1451 packet_store((uint8 *)&eh->en_tag_ctrl, 2, 1452 VLAN_CTRL(0, 0, pi->added_vlan) << 16, 0); 1453 packet_store((uint8*)eh + 16, 4, seq_no++, 0); 1454 1455 /* 1456 * Fill data from after header & seq # to end of packet. 1457 * Byte data starts with the pattern MSByte through LSByte 1458 * and recycles. 1459 */ 1460 cur_offset = 20; 1461 pattern = packet_store((uint8*)eh + cur_offset, 1462 pkt->pkt_data[0].len - cur_offset, 1463 pattern, SS_PATTERN_INC); 1464 1465 /* Store the sequence number of the packet */ 1466 sequence_p = (uint8 *)eh + LB2_ID_POS; 1467 *sequence_p = seq_no; 1468 1469 pkt_idx++; 1470 } 1471 } 1472 } 1473 1474 STATIC int 1475 ss_lbu_monitor_start(int unit) 1476 { 1477 ssi.lw[unit].sema = sal_sem_create("ss-sema", sal_sem_BINARY, 0); 1478 if (ssi.lw[unit].sema == NULL) { 1479 return (-1); 1480 } 1481 1482 ssi.lw[unit].sema_woke = FALSE; 1483 1484 /* Now that all mems are safely created, fire off the handler */ 1485 /* Let rx handler ignore packets until testing */ 1486 ssi.lw[unit].expect_pkts = FALSE; 1487 ssi.lw[unit].rx_pkt_cnt = 0; 1488 ssi.lw[unit].tx_ppt = ssi.num_packets[unit]; /* For use in callback */ 1489 if (lbu_port_monitor_task(unit, lbu_rx_callback, &(ssi.lw[unit])) < 0) { 1490 return (-1); 1491 } 1492 1493 /* Wiring up required data to fake out the lbu subsystem */ 1494 ssi.lw[unit].current_test_type = LB2_TT_SNAKE; 1495 ssi.lw[unit].set_up = TRUE; 1496 ssi.lw[unit].cur_params = &(ssi.lw[unit].params[LB2_TT_SNAKE]); 1497 ssi.lw[unit].cur_params->loopback = LB2_MODE_PHY; 1498 1499 return(0); 1500 } 1501 1502 STATIC int 1503 system_snake_init(system_snake_opts_t *opts) 1504 { 1505 int unit = 0, rv; 1506 int i; 1507 bcm_pbmp_t all_ethernets_pbm, ignore_pbm; 1508 int sysid = opts->sysid; 1509 #ifndef NO_SAL_APPL 1510 char *init_soc_file; 1511 #endif 1512 1513 if (opts->verbose) { 1514 cli_out("Initializing system snake\n"); 1515 } 1516 1517 memset(&ssi, 0, sizeof(ssi)); 1518 1519 SS_UNIT_ITER(sysid, unit) { 1520 /* 1521 * Load system defaults from rc.soc 1522 */ 1523 1524 sh_swap_unit_vars(unit); 1525 1526 #ifndef NO_SAL_APPL 1527 if (diag_rc_load(unit) != CMD_OK) { 1528 cli_out("Test: ERROR: RC init script " 1529 "for system snake test failed\n"); 1530 return (-1); 1531 } 1532 1533 /* 1534 * Load system snake soc dcript. 1535 */ 1536 if ((init_soc_file = ss_init_file[sysid]) && 1537 sh_rcload_file(unit, NULL, init_soc_file, FALSE) != CMD_OK) { 1538 cli_out("Test: ERROR: %s init script " 1539 "for system snake test failed\n", SS_SOC_SCRIPT); 1540 return (-1); 1541 } 1542 #endif 1543 1544 ssi.stats[unit] = 1545 sal_alloc(SOC_MAX_NUM_PORTS * sizeof(lb2_port_stat_t), 1546 "SS statistics"); 1547 if (!ssi.stats[unit]) { 1548 cli_out("Unable to allocate statistics memory\n"); 1549 return BCM_E_MEMORY; 1550 } 1551 1552 /* 1553 * Configuring chips for the test 1554 */ 1555 1556 if (ss_unit_setup(opts, unit) < 0) { 1557 cli_out("%s: Unit setup failed\n", SOC_UNIT_NAME(unit)); 1558 return (-1); 1559 } 1560 } 1561 1562 /* 1563 * Wait for restarted links to come up on all e-ports on each unit 1564 */ 1565 if (opts->mode == SS_MODE_EXT) { 1566 cli_out("Checking external links... "); 1567 SS_UNIT_ITER(sysid, unit) { 1568 BCM_PBMP_ASSIGN(all_ethernets_pbm, pcfg[unit].e); 1569 if (soc_property_get_str(unit, spn_SS_IGNORE_PBMP)) { 1570 ignore_pbm = soc_property_get_bcm_pbmp(unit, spn_SS_IGNORE_PBMP, 0); 1571 BCM_PBMP_REMOVE(all_ethernets_pbm, ignore_pbm); 1572 } 1573 if ((rv = bcm_link_wait(unit,&all_ethernets_pbm, 20000000)) < 0) { 1574 test_error(unit, 1575 "Unit %d: Failed to complete autonegotiation: %s\n" 1576 "Check front panel cables\n", 1577 unit, bcm_errmsg(rv)); 1578 return(-1); /* In case they continue */ 1579 } 1580 } 1581 cli_out("up\n"); 1582 } 1583 1584 /* 1585 * Define port interconnections 1586 */ 1587 if ((rv = ss_port_interconnect_define(opts)) < 0) { 1588 test_error(unit, 1589 "Failed to define port interconnects: %s\n", 1590 bcm_errmsg(rv)); 1591 return(-1); 1592 } 1593 1594 /* 1595 * Execute port interconnections 1596 */ 1597 if ((rv = ss_port_interconnect_execute(opts)) < 0) { 1598 test_error(unit, 1599 "Failed to execute port interconnects: %s\n", 1600 bcm_errmsg(rv)); 1601 return(-1); 1602 } 1603 1604 /* 1605 * Find the units that will be used to inject and extract packets 1606 */ 1607 ss_io_units_find(opts); 1608 1609 for (i = 0; i < ssi.io_unit_num; i++) { 1610 unit = ssi.io_unit[i]; 1611 1612 /* 1613 * Allocate memory for Tx packets, Rx packets and packet match markers 1614 */ 1615 if ((rv = ss_packet_alloc(opts, unit)) < 0) { 1616 test_error(unit, 1617 "Failed to allocate Tx or Rx packets: %s\n", 1618 bcm_errmsg(rv)); 1619 return (-1); 1620 } 1621 1622 /* 1623 * Fill individual Tx packets 1624 */ 1625 ss_tx_packet_fill(opts, unit); 1626 1627 /* 1628 * Start loopback monitors 1629 */ 1630 if ((rv = ss_lbu_monitor_start(unit)) < 0) { 1631 test_error(unit, 1632 "Failed to start loopback monitor thread: %s\n", 1633 bcm_errmsg(rv)); 1634 return (-1); 1635 } 1636 } 1637 1638 return 0; 1639 } 1640 1641 static int 1642 system_snake_stats(int unit, bcm_pbmp_t bitmap, lb2_port_stat_t stats[]) 1643 { 1644 /* 1645 * NB: We choose "SOC_IS_XGS(unit)" for the third argument so 1646 * that traffic checking is disabled on fabrics. This is to 1647 * prevent complaint on the external loopbacks. 1648 */ 1649 1650 return lbu_snake_stats(unit, bitmap, 1651 (SOC_IS_XGS(unit)) ? LB2_MODE_EXT : LB2_MODE_PHY, 1652 stats); 1653 } 1654 1655 int 1656 system_snake_run(system_snake_opts_t *opts) 1657 { 1658 int unit, rv, ix, io_unit; 1659 int i, port; 1660 int timer, sleep_time; 1661 int no_packets; 1662 lb2s_port_connect_t *pi; 1663 int snake; 1664 int num_packets; 1665 int sysid = opts->sysid; 1666 system_snake_list_t *snake_list = ss_snake_table[sysid]; 1667 int snake_num = ss_num_paths[sysid]; 1668 1669 /* Counter records init */ 1670 SS_UNIT_ITER(sysid, unit) { 1671 for (ix = 0; ix < SOC_MAX_NUM_PORTS; ix++) { 1672 ssi.stats[unit][ix].initialized = FALSE; 1673 } 1674 1675 BCM_PBMP_ITER(pcfg[unit].port, port) { 1676 if ((rv = bcm_stat_clear(unit, port)) < 0) { 1677 test_error(unit, 1678 "Could not clear counters: %s\n", 1679 bcm_errmsg(rv)); 1680 return -1; 1681 } 1682 } 1683 1684 /* This is the init call */ 1685 if (system_snake_stats(unit, pcfg[unit].port, 1686 ssi.stats[unit]) < 0) { 1687 lbu_snake_dump_stats(unit, pcfg[unit].port, ssi.stats[unit]); 1688 return (-1); 1689 } 1690 } 1691 1692 /* TX packets */ 1693 if (opts->verbose) { 1694 cli_out("Transmitting packets\n"); 1695 } 1696 1697 for (i = 0; i < ssi.io_unit_num; i++) { 1698 io_unit = ssi.io_unit[i]; 1699 1700 num_packets = ssi.num_packets[io_unit]; 1701 1702 if (opts->verbose) { 1703 cli_out("\t%d packets to unit %d\n", num_packets, io_unit); 1704 } 1705 1706 for (ix = 0; ix < num_packets; ix++ ) { 1707 if ((rv = bcm_tx(io_unit, 1708 ssi.lw[io_unit].tx_pkts[ix], NULL)) < 0) { 1709 cli_out("System snake TX pkt %d: ERROR: bcm_tx: %s\n", 1710 ix, bcm_errmsg(rv)); 1711 } 1712 } 1713 } 1714 1715 cli_out("Running (%d seconds): Speed=%s Mode=%s\n", 1716 opts->duration, 1717 ss_speed_str[opts->speed], 1718 ss_mode_str[opts->mode]); 1719 1720 /* Wait, monitor counters */ 1721 timer = 0; 1722 no_packets = 0; 1723 while (timer < opts->duration) { 1724 if ((opts->duration - timer) < opts->interval) 1725 sleep_time = opts->duration - timer; 1726 else 1727 sleep_time = opts->interval; 1728 1729 sal_sleep(sleep_time); 1730 timer += sleep_time; 1731 cli_out("Time elapsed: %d seconds %s\n", timer, 1732 (timer>=opts->duration)?"(end of test)":""); 1733 1734 SS_UNIT_ITER(sysid, unit) { 1735 if (system_snake_stats(unit, 1736 pcfg[unit].port, ssi.stats[unit]) < 0) { 1737 no_packets = 1; 1738 break; 1739 } 1740 } 1741 1742 if (no_packets) { 1743 break; 1744 } 1745 } 1746 1747 if (no_packets) { 1748 SS_UNIT_ITER(sysid, unit) { 1749 cli_out("Counters for unit %d (%s)\n", unit, SOC_UNIT_NAME(unit)); 1750 system_snake_stats(unit, pcfg[unit].port, ssi.stats[unit]); 1751 lbu_snake_dump_stats(unit, pcfg[unit].port, ssi.stats[unit]); 1752 } 1753 1754 cli_out("\nSystem snake test FAILED\n"); 1755 1756 return (-1); 1757 } 1758 1759 /* Let the packets out */ 1760 for (snake = 0 ; snake < snake_num; snake++) { 1761 int return_unit; 1762 1763 return_unit = io_unit = snake_list[snake].snake_path->conn[0].unit; 1764 /* 1765 * For external loopback, we may need to set up the filter on 1766 * a unit that is different than the one on which the packet was 1767 * transmitted. 1768 */ 1769 if (opts->mode == SS_MODE_EXT) { 1770 return_unit = snake_list[snake].snake_path->return_unit; 1771 } 1772 1773 ssi.lw[io_unit].unit = io_unit; 1774 ssi.lw[io_unit].expect_pkts = TRUE; 1775 1776 pi = &(ssi.cmic_return_pi[snake]); 1777 if (opts->verbose) { 1778 cli_out("Redirect %d to CPU\n", pi->added_vlan - SS_VLAN_BASE); 1779 } 1780 if ((rv = lbu_connect_ports(return_unit, pi, TRUE)) < 0) { 1781 test_error(io_unit, 1782 "CPU redirect failure on snake %d: %s\n", 1783 snake, bcm_errmsg(rv)); 1784 return -1; 1785 } 1786 1787 sal_usleep(SS_INTERPATH_WAIT); /* To let packets drain */ 1788 } 1789 1790 /* Retrieve packets */ 1791 for (i = 0; i < ssi.io_unit_num; i++) { 1792 io_unit = ssi.io_unit[i]; 1793 1794 if (opts->verbose) { 1795 cli_out("Retrieving packets from unit %d\n", io_unit); 1796 } 1797 1798 if (sal_sem_take(ssi.lw[io_unit].sema, 1799 soc_property_get(io_unit, 1800 spn_DIAG_LB_PACKET_TIMEOUT, 1801 5) * SECOND_USEC)) { 1802 cli_out("\nTime-out waiting for snake completion on unit %d\n", 1803 io_unit); 1804 cli_out("Receive count is %d; expecting %d pkts.\n\n", 1805 ssi.lw[io_unit].rx_pkt_cnt, ssi.num_packets[io_unit]); 1806 1807 SS_UNIT_ITER(sysid, unit) { 1808 system_snake_stats(unit, pcfg[unit].port, 1809 ssi.stats[unit]); 1810 lbu_snake_dump_stats(unit, pcfg[unit].port, 1811 ssi.stats[unit]); 1812 } 1813 1814 ssi.lw[io_unit].sema_woke = FALSE; 1815 1816 return (-1); 1817 } 1818 1819 ssi.lw[io_unit].sema_woke = FALSE; 1820 ssi.lw[io_unit].expect_pkts = FALSE; /* Let RX handler ignore pkts */ 1821 1822 /* Check counters and packets */ 1823 if (opts->verbose) { 1824 cli_out("Checking packets received from unit %d\n", io_unit); 1825 } 1826 1827 if (lbu_snake_analysis(&(ssi.lw[io_unit])) < 0) { 1828 SS_UNIT_ITER(sysid, unit) { 1829 if (system_snake_stats(unit, pcfg[unit].port, 1830 ssi.stats[unit]) < 0) { 1831 1832 } 1833 lbu_snake_dump_stats(unit, pcfg[unit].port, 1834 ssi.stats[unit]); 1835 } 1836 return (-1); 1837 } 1838 1839 for (ix = 0; ix < ssi.num_packets[io_unit]; ix++) { 1840 if (ssi.lw[io_unit].tx_pkt_match[ix] == 0) { 1841 cli_out("\nTX packet %d did not return to CPU\n", (ix + 1)); 1842 } 1843 } 1844 } 1845 1846 /* 1847 * Do the final stats 1848 */ 1849 if (opts->verbose) { 1850 SS_UNIT_ITER(sysid, unit) { 1851 cli_out("Counters for unit %d (%s)\n", unit, SOC_UNIT_NAME(unit)); 1852 system_snake_stats(unit, pcfg[unit].port, ssi.stats[unit]); 1853 lbu_snake_dump_stats(unit, pcfg[unit].port, ssi.stats[unit]); 1854 } 1855 } 1856 1857 cli_out("Passed\n"); 1858 1859 return 0; 1860 } 1861 1862 STATIC int 1863 system_snake_done(system_snake_opts_t *opts) 1864 { 1865 int unit, ix, i, rv; 1866 1867 /* Unregister the callback */ 1868 for (ix = 0; ix < ssi.io_unit_num; ix++) { 1869 unit = ssi.io_unit[ix]; 1870 1871 if (opts->verbose) { 1872 cli_out("Unregistering Rx callback on unit %d\n", unit); 1873 } 1874 1875 if ((rv = bcm_rx_unregister(unit, lbu_rx_callback, 1876 BCM_RX_PRIO_MAX)) < 0) { 1877 cli_out("Failed to unregister RX handler.\n"); 1878 } 1879 1880 if (opts->verbose) { 1881 cli_out("Stopping Rx on unit %d\n", unit); 1882 } 1883 1884 if ((rv = bcm_rx_stop(unit, NULL)) < 0) { 1885 cli_out("system_snake_done: could not stop packet driver: %s\n", 1886 bcm_errmsg(rv)); 1887 } 1888 1889 /* Flush out tx packets */ 1890 if (ssi.lw[unit].tx_pkts) { 1891 bcm_pkt_blk_free(unit, ssi.lw[unit].tx_pkts, 1892 ssi.num_packets[unit]); 1893 ssi.lw[unit].tx_pkts = NULL; 1894 } 1895 1896 if (ssi.lw[unit].tx_pkt_match) { 1897 sal_free(ssi.lw[unit].tx_pkt_match); 1898 ssi.lw[unit].tx_pkt_match = NULL; 1899 } 1900 1901 /* Flush out rx packets */ 1902 if (ssi.lw[unit].rx_pkts) { 1903 for (i = 0; i < ssi.num_packets[unit]; i++) { 1904 if (ssi.lw[unit].rx_pkts[i]._pkt_data.data) { 1905 bcm_rx_free(unit, ssi.lw[unit].rx_pkts[i]._pkt_data.data); 1906 } 1907 } 1908 sal_free(ssi.lw[unit].rx_pkts); 1909 ssi.lw[unit].rx_pkts = NULL; 1910 } 1911 1912 if (ssi.lw[unit].sema) { 1913 sal_sem_destroy(ssi.lw[unit].sema); 1914 ssi.lw[unit].sema = NULL; 1915 } 1916 1917 if (ssi.stats[unit]) { 1918 sal_free(ssi.stats[unit]); 1919 ssi.stats[unit] = NULL; 1920 } 1921 } 1922 1923 return 0; 1924 } 1925 1926 int 1927 system_snake_test(system_snake_opts_t *opts) 1928 { 1929 int rv, d_rv; 1930 1931 /* Configure system */ 1932 if ((rv = system_snake_init(opts)) < 0) { 1933 goto cleanup; 1934 } 1935 1936 /* Transmit packets, wait, check */ 1937 rv = system_snake_run(opts); 1938 1939 cleanup: 1940 /* Clean up data structures */ 1941 if ((d_rv = system_snake_done(opts)) < 0) { 1942 return d_rv; 1943 } 1944 1945 return (rv < 0) ? rv : d_rv; 1946 } 1947 1948 char cmd_ss_usage[] = 1949 "ss [Duration=<secs>] [CheckInterval=<secs>]\n\t" 1950 " [Mode=MAC|PHY|EXT] [Speed=MAX|10|100|1000|2500|10G]\n\t" 1951 "Test system with snaked packets.\n\t" 1952 "This test is supported only for certain platforms.\n\t" 1953 "HiGig cables must be looped back in pairs.\n\t" 1954 "Defaults: Duration=10, CheckInterval=5, Mode=PHY, " 1955 "Speed=DEFAULT(from rc.soc).\n" ; 1956 1957 cmd_result_t 1958 cmd_ss(int unit, args_t *args) 1959 { 1960 system_snake_opts_t opts; 1961 parse_table_t pt; 1962 int sysid, rv; 1963 1964 /* 1965 * Make sure that our current hardware is in the 1966 * list of platforms that support the ss command. 1967 */ 1968 1969 for (sysid = 0; sysid < SS_SYSID_NUM; sysid++) { 1970 if (soc_cm_config_var_get(unit, ss_sysid_str[sysid])) { 1971 break; 1972 } 1973 } 1974 1975 if (sysid == SS_SYSID_NUM) { 1976 cli_out("This test only runs on certain platforms.\n"); 1977 cli_out("One of the following config variables must be\n"); 1978 cli_out("set to indicate the platform:\n"); 1979 for (sysid = 0; sysid < SS_SYSID_NUM; sysid++) { 1980 cli_out(" %s\n", ss_sysid_str[sysid]); 1981 } 1982 1983 return CMD_FAIL; 1984 } 1985 1986 /* cli_out("%s baseboard detected\n",ss_sysid_str[sysid]); */ 1987 1988 opts.got_herc = TRUE; 1989 opts.sysid = sysid; 1990 1991 /* Default values */ 1992 opts.duration = SS_DURATION; 1993 opts.interval = SS_INTERVAL; 1994 opts.speed = SS_SPEED_DEFAULT; 1995 if (sysid == SS_SYSID_FIREBOLT) { 1996 opts.mode = SS_MODE_EXT; 1997 } else { 1998 opts.mode = SS_MODE_PHY; 1999 } 2000 opts.verbose = FALSE; 2001 opts.pli = -1; 2002 2003 parse_table_init(unit, &pt); 2004 parse_table_add(&pt, "Duration", PQ_INT|PQ_DFL, 0, 2005 &opts.duration, NULL); 2006 parse_table_add(&pt, "CheckInterval", PQ_INT|PQ_DFL, 0, 2007 &opts.interval, NULL); 2008 parse_table_add(&pt, "Speed", PQ_MULTI|PQ_DFL, 0, 2009 &opts.speed, ss_speed_str); 2010 parse_table_add(&pt, "Mode", PQ_MULTI|PQ_DFL, 0, 2011 &opts.mode, ss_mode_str); 2012 parse_table_add(&pt, "Verbose", PQ_BOOL|PQ_DFL, 0, 2013 &opts.verbose, NULL); 2014 parse_table_add(&pt, "LengthIncrement", PQ_INT|PQ_DFL, 0, 2015 &opts.pli, NULL); 2016 2017 if (parse_arg_eq(args, &pt) < 0) { 2018 parse_arg_eq_done(&pt); 2019 return(CMD_USAGE); 2020 } 2021 2022 if (ARG_CNT(args) > 0) { 2023 cli_out("%s: Unrecognized extra argument: %s\n", 2024 ARG_CMD(args), ARG_CUR(args)); 2025 parse_arg_eq_done(&pt); 2026 return CMD_USAGE; 2027 } 2028 2029 parse_arg_eq_done(&pt); 2030 2031 /* 2032 * Police any cmd line parameters 2033 */ 2034 2035 if (sysid == SS_SYSID_FIREBOLT) { 2036 if (opts.mode != SS_MODE_EXT) { 2037 cli_out("%s Mode not supported on %s platform. Use tr 39 instead.\n", 2038 ss_mode_str[opts.mode], ss_sysid_str[sysid]); 2039 return CMD_FAIL; 2040 } 2041 } 2042 2043 if (opts.duration < opts.interval) { 2044 opts.interval = opts.duration; 2045 } 2046 2047 if (opts.speed == SS_SPEED_MAX) { 2048 opts.speed = SS_SPEED_DEFAULT; 2049 } 2050 2051 if (opts.pli > 0) { 2052 ss_set_packet_length_increment(&opts); 2053 } 2054 2055 rv = system_snake_test(&opts); 2056 2057 /* 2058 * Restore current unit since system_snake_test() changes it. 2059 */ 2060 2061 sh_swap_unit_vars(unit); 2062 2063 return rv; 2064 } 2065 2066 #endif /* INCLUDE_TEST */ 2067 2068 int _diag_system_snake_not_empty;