streaming_l3uc.c (31417B)
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 * The l3uc test checks TDM and L3 unicast functionality and performance by 8 * streaming IPv4/IPv6 packets on all ports at maximum rate. All ports are 9 * configured in MAC loopback mode and each port is paired with a same speed 10 * port. The test calculates the number of packets needed to saturate the ports 11 * and send the IPv4/IPv6 packets from the CPU to each port pairs initially. 12 * Then the packets are L3 switched between the port pairs indefinitely. The 13 * MAC DA, MAC SA, and VLAN are changed every time a packet is L3 switched. Once 14 * the traffic reaches steady state, rate calculation is done by dividing the 15 * transmit packet count changes and transmit byte count changes over a 16 * programmable interval. The rates are checked against expected rates based on 17 * port configuration and oversubscription ratio. Finally, packet integrity 18 * check is achieved by redirecting the packets back to the CPU and compared 19 * against expected packets. 20 * 21 * Configuration parameters passed from CLI: 22 * PktSize: Packet size in bytes. Set to 0 for worst case packet sizes on all 23 * ports (145B for ENET, 76B for HG2). Set to 1 for random packet sizes 24 * FloodCnt: Number of packets in each swill. Setting this to 0 will let the 25 * test calculate the number of packets that can be sent to achieve 26 * a lossless swirl at full rate. Set to 0 by default. 27 * RateCalcInt: Interval in seconds over which rate is to be calculated 28 * TolLr: Rate tolerance percentage for linerate ports (1% by default). 29 * TolOv: Rate tolerance percentage for oversubscribed ports (3% by default). 30 * ChkPktInteg: Set to 0 to disable packet integrity checks, 1 to enable 31 (default). 32 * MaxNumCells: Max number of cells for random packet sizes. Default = 4. Set 33 * to 0 for random. 34 * IPv6: Set to 1 to send IPv6 packets, 0 to send IPv4 packets (default). 35 */ 36 37 #include <appl/diag/system.h> 38 #include <shared/alloc.h> 39 #include <shared/bsl.h> 40 41 #include <soc/cm.h> 42 #include <soc/dma.h> 43 #include <soc/drv.h> 44 #include <soc/dcb.h> 45 #include <soc/cmicm.h> 46 #include <soc/cmic.h> 47 48 #include <sal/types.h> 49 #include <appl/diag/parse.h> 50 #include <bcm/port.h> 51 #include <bcm/vlan.h> 52 53 #include "testlist.h" 54 #include "gen_pkt.h" 55 #include "streaming_lib.h" 56 57 #define MAC_DA {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc} 58 #define MAC_SA {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54} 59 #define VLAN 0x0a00 60 #define TTL 255 61 #define IPV4_ADDR 0xc0a80001 62 #define IPV6_ADDR { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 63 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x00, 0x01 }; 64 65 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_L3) && \ 66 (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)) 67 68 #define PKT_SIZE_PARAM_DEFAULT 0 69 #define FLOOD_PKT_CNT_PARAM_DEFAULT 0 70 #define RATE_CALC_INTERVAL_PARAM_DEFAULT 10 71 #define RATE_TOLERANCE_LR_PARAM_DEFAULT 1 72 #define RATE_TOLERANCE_OV_PARAM_DEFAULT 3 73 #define CHECK_PACKET_INTEGRITY_PARAM_DEFAULT 1 74 #define MAX_NUM_CELLS_PARAM_DEFAULT 4 75 #define IPV6_PARAM_DEFAULT 0 76 #define SPEEDUP_FACTOR_PARAM_DEFAULT 1 77 78 typedef struct l3uc_s { 79 uint32 pkt_size_param; 80 uint32 flood_pkt_cnt_param; 81 uint32 rate_calc_interval_param; 82 uint32 rate_tolerance_lr_param; 83 uint32 rate_tolerance_ov_param; 84 uint32 check_packet_integrity_param; 85 uint32 max_num_cells_param; 86 uint32 loopback_mode_param; 87 uint32 scaling_factor_param; 88 uint32 ipv6_param; 89 uint32 dst_port[SOC_MAX_NUM_PORTS]; 90 uint32 bad_input; 91 int test_fail; 92 uint32 pkt_seed; 93 uint32 **rand_pkt_sizes; 94 } l3uc_t; 95 96 static l3uc_t *l3uc_parray[SOC_MAX_NUM_DEVICES]; 97 /* static rate_calc_t *rate_calc_parray[SOC_MAX_NUM_DEVICES]; */ 98 99 const char l3uc_test_usage[] = 100 #ifdef COMPILER_STRING_CONST_LIMIT 101 "\nDocumentation too long to be displayed with -pedantic compiler\n"; 102 #else 103 "L3UC test usage:\n" 104 " \n" 105 "PktSize: Packet size in bytes. Set to 1 for random packet sizes.\n" 106 " Set to 0 (default) for worst case packet sizes on all ports\n" 107 " (145B for ENET, 76B for HG2).\n" 108 "FloodCnt: Number of packets swirl between each port pair.\n" 109 " Set to 0 (default) for a lossless swirl at full rate.\n" 110 "RateCalcInt: Interval in seconds over which rate is to be calculated.\n" 111 "TolLr: Rate tolerance percentage for line rate ports.\n" 112 " (1 percentage by default)\n" 113 "TolOv: Rate tolerance percentage for oversubscribed ports.\n" 114 " (3 percentage by default).\n" 115 "ChkPktInteg: Set to 0 to disable packet integrity checks.\n" 116 " Set to 1 to enable (default).\n" 117 "MaxNumCells: Maximum number of cells for random packet sizes.\n" 118 " Set to 0 for random cell sizes. (default is 4)\n" 119 "LoopbackMode: Loopback mode. Set to 1 for MAC loopback, 2 for PHY loopback.\n" 120 " (default is MAC loopback)\n" 121 "IPv6: Set to 1 to send IPv6 packets; 0 to send IPv4 (default).\n" 122 ; 123 #endif 124 125 126 /* 127 * Function: 128 * l3uc_parse_test_params 129 * Purpose: 130 * Parse CLI parameters, create test structure and flag bad inputs. 131 * Parameters: 132 * unit - StrataSwitch Unit #. 133 * a - Pointer to arguments 134 * 135 * Returns: 136 * Nothing 137 * Notes: 138 * l3uc_p->bad_input set from here - tells test to crash out in case 139 * CLI input combination is invalid. 140 */ 141 static void 142 l3uc_parse_test_params(int unit, args_t *a) 143 { 144 parse_table_t parse_table; 145 l3uc_t *l3uc_p = l3uc_parray[unit]; 146 uint32 min_pkt_size = l3uc_p->ipv6_param ? MIN_IPV6_PKT_SIZE : MIN_PKT_SIZE; 147 148 /* default parameter value */ 149 l3uc_p->bad_input = 0; 150 l3uc_p->pkt_size_param = PKT_SIZE_PARAM_DEFAULT; 151 l3uc_p->flood_pkt_cnt_param = FLOOD_PKT_CNT_PARAM_DEFAULT; 152 l3uc_p->rate_calc_interval_param = RATE_CALC_INTERVAL_PARAM_DEFAULT; 153 l3uc_p->rate_tolerance_lr_param = RATE_TOLERANCE_LR_PARAM_DEFAULT; 154 l3uc_p->rate_tolerance_ov_param = RATE_TOLERANCE_OV_PARAM_DEFAULT; 155 l3uc_p->check_packet_integrity_param 156 = CHECK_PACKET_INTEGRITY_PARAM_DEFAULT; 157 l3uc_p->max_num_cells_param = MAX_NUM_CELLS_PARAM_DEFAULT; 158 l3uc_p->loopback_mode_param = BCM_PORT_LOOPBACK_MAC; 159 l3uc_p->ipv6_param = IPV6_PARAM_DEFAULT; 160 l3uc_p->scaling_factor_param = SPEEDUP_FACTOR_PARAM_DEFAULT; 161 162 /*Parse CLI opts */ 163 parse_table_init(unit, &parse_table); 164 parse_table_add(&parse_table, "PktSize", PQ_INT|PQ_DFL, 0, 165 &(l3uc_p->pkt_size_param), NULL); 166 parse_table_add(&parse_table, "FloodCnt", PQ_INT|PQ_DFL, 0, 167 &(l3uc_p->flood_pkt_cnt_param), NULL); 168 parse_table_add(&parse_table, "RateCalcInt", PQ_INT|PQ_DFL, 0, 169 &(l3uc_p->rate_calc_interval_param), NULL); 170 parse_table_add(&parse_table, "TolLr", PQ_INT|PQ_DFL, 0, 171 &(l3uc_p->rate_tolerance_lr_param), NULL); 172 parse_table_add(&parse_table, "TolOv", PQ_INT|PQ_DFL, 0, 173 &(l3uc_p->rate_tolerance_ov_param), NULL); 174 parse_table_add(&parse_table, "ChkPktInteg", PQ_INT|PQ_DFL, 0, 175 &(l3uc_p->check_packet_integrity_param), NULL); 176 parse_table_add(&parse_table, "MaxNumCells", PQ_INT|PQ_DFL, 0, 177 &(l3uc_p->max_num_cells_param), NULL); 178 parse_table_add(&parse_table, "LoopbackMode", PQ_INT|PQ_DFL, 0, 179 &l3uc_p->loopback_mode_param, NULL); 180 parse_table_add(&parse_table, "IPv6", PQ_INT|PQ_DFL, 0, 181 &(l3uc_p->ipv6_param), NULL); 182 parse_table_add(&parse_table, "ScalingFactor", PQ_INT|PQ_DFL, 0, 183 &(l3uc_p->scaling_factor_param), NULL); 184 185 if (parse_arg_eq(a, &parse_table) < 0 || ARG_CNT(a) != 0) { 186 cli_out("%s", l3uc_test_usage); 187 test_error(unit, "\n*ERROR PARSING ARGS\n"); 188 } 189 190 cli_out("\n"); 191 cli_out("------------- PRINTING TEST PARAMS ------------------\n"); 192 cli_out("PktSize = %0d\n", l3uc_p->pkt_size_param); 193 cli_out("RateCalcInt = %0d\n", l3uc_p->rate_calc_interval_param); 194 cli_out("FloodCnt = %0d\n", l3uc_p->flood_pkt_cnt_param); 195 cli_out("TolLr = %0d\n", l3uc_p->rate_tolerance_lr_param); 196 cli_out("TolOv = %0d\n", l3uc_p->rate_tolerance_ov_param); 197 cli_out("ChkPktInteg = %0d\n", l3uc_p->check_packet_integrity_param); 198 cli_out("MaxNumCells = %0d\n", l3uc_p->max_num_cells_param); 199 cli_out("LoopbackMode = %0d\n", l3uc_p->loopback_mode_param); 200 cli_out("IPv6 = %0d\n", l3uc_p->ipv6_param); 201 cli_out("ScalingFactor= %0d\n", l3uc_p->scaling_factor_param); 202 cli_out("-----------------------------------------------------\n"); 203 204 if (l3uc_p->max_num_cells_param == 0) { 205 /* coverity[dont_call : FALSE] */ 206 l3uc_p->max_num_cells_param = (sal_rand() % (MTU_CELL_CNT - 1)) + 1; 207 } 208 209 if (l3uc_p->pkt_size_param == 0) { 210 cli_out 211 ("\nUsing worst case packet sizes - 145B for Ethernet " 212 "and 76B (64B + 12B hg-hdr) for HG2"); 213 } else if (l3uc_p->pkt_size_param == 1) { 214 cli_out("\nUsing random packet sizes"); 215 } else if (l3uc_p->pkt_size_param < min_pkt_size) { 216 test_error(unit,"\n*ERROR: Packet size cannot be lower than %0dB\n", 217 min_pkt_size); 218 l3uc_p->bad_input = 1; 219 } else if (l3uc_p->pkt_size_param > MTU) { 220 test_error(unit,"\n*ERROR: Packet size higher than %0dB (Device MTU)\n", 221 MTU); 222 l3uc_p->bad_input = 1; 223 } 224 225 if (l3uc_p->flood_pkt_cnt_param == 0) { 226 cli_out("\nFloodCnt=0, test will automatically calculate number of" 227 " packets to flood each port"); 228 } 229 } 230 231 /* 232 * Function: 233 * l3uc_set_port_property 234 * Purpose: 235 * Set rand_pkt_sizes arrays. 236 * Parameters: 237 * unit: StrataSwitch Unit #. 238 * pbmp - Device port bitmap 239 * pkt_size_param - Packet size in bytes 240 * max_num_cells_param - Maximum number of cells 241 * 242 * Returns: 243 * Nothing 244 */ 245 static void 246 l3uc_set_port_property(int unit, pbmp_t pbmp, int pkt_size_param, 247 int max_num_cells_param) 248 { 249 int p, j; 250 uint32 pkt_size; 251 l3uc_t *l3uc_p = l3uc_parray[unit]; 252 253 l3uc_p->rand_pkt_sizes = 254 (uint32 **) sal_alloc(SOC_MAX_NUM_PORTS * sizeof(uint32 *), 255 "rand_pkt_sizes_array*"); 256 257 for (p = 0; p < SOC_MAX_NUM_PORTS; p++) { 258 l3uc_p->rand_pkt_sizes[p] = 259 (uint32 *) sal_alloc(TARGET_CELL_COUNT * sizeof(uint32), 260 "rand_pkt_sizes_array"); 261 } 262 263 PBMP_ITER(pbmp, p) { 264 if (p < SOC_MAX_NUM_PORTS) { 265 for (j = 0; j < TARGET_CELL_COUNT; j++) { 266 do { 267 /* coverity[dont_call : FALSE] */ 268 pkt_size = (sal_rand() % (MTU - MIN_PKT_SIZE + 1)) + 269 MIN_PKT_SIZE; 270 } while (stream_get_pkt_cell_cnt(unit, pkt_size, p) > 271 max_num_cells_param); 272 l3uc_p->rand_pkt_sizes[p][j] = pkt_size; 273 } 274 } 275 } 276 } 277 278 /* 279 * Function: 280 * l3uc_set_up_ports 281 * Purpose: 282 * Enable port bridging and HiGig lookup for HG2 ports 283 * Parameters: 284 * unit - StrataSwitch Unit #. 285 * pbmp - Device port bitmap 286 * 287 * Returns: 288 * Nothing 289 */ 290 static void 291 l3uc_set_up_ports(int unit, pbmp_t pbmp) 292 { 293 int i, p; 294 lport_tab_entry_t lport_tab_entry; 295 port_tab_entry_t port_tab_entry; 296 soc_field_t ihg_lookup_fields[] = { 297 HYBRID_MODE_ENABLEf, 298 USE_MH_PKT_PRIf, 299 USE_MH_VIDf, 300 HG_LOOKUP_ENABLEf, 301 REMOVE_MH_SRC_PORTf 302 }; 303 uint32 ihg_lookup_values[] = { 0x0, 0x1, 0x1, 0x1, 0x0 }; 304 305 cli_out("\nEnabling HG_LOOKUP on HG ports"); 306 if (SOC_REG_IS_VALID(unit, IHG_LOOKUPr)) { 307 PBMP_ITER(pbmp, p) { 308 if (p < SOC_MAX_NUM_PORTS && IS_HG_PORT(unit, p)) { 309 soc_reg_fields32_modify(unit, IHG_LOOKUPr, p, 5, 310 ihg_lookup_fields, ihg_lookup_values); 311 } 312 } 313 } else { 314 cli_out("\n*ERROR, invalid reg %s\n", SOC_REG_NAME(unit, IHG_LOOKUPr)); 315 } 316 317 cli_out("\nEnabling Port bridging"); 318 if (SOC_MEM_IS_VALID(unit, LPORT_TABm)) { 319 for (i = 0; i < soc_mem_index_max(unit, LPORT_TABm); i++) { 320 (void) soc_mem_read(unit, LPORT_TABm, COPYNO_ALL, i, 321 lport_tab_entry.entry_data); 322 soc_mem_field32_set(unit, LPORT_TABm, lport_tab_entry.entry_data, 323 ALLOW_SRC_MODf, 0x1); 324 soc_mem_field32_set(unit, LPORT_TABm, lport_tab_entry.entry_data, 325 PORT_BRIDGEf, 0x1); 326 (void) soc_mem_write(unit, LPORT_TABm, COPYNO_ALL, i, 327 lport_tab_entry.entry_data); 328 } 329 } else { 330 cli_out("\n*ERROR, invalid mem %s\n", SOC_MEM_NAME(unit, LPORT_TABm)); 331 } 332 333 if (SOC_MEM_IS_VALID(unit, PORT_TABm)) { 334 for (i = 0; i < soc_mem_index_max(unit, PORT_TABm); i++) { 335 (void) soc_mem_read(unit, PORT_TABm, COPYNO_ALL, i, 336 port_tab_entry.entry_data); 337 soc_mem_field32_set(unit, PORT_TABm, port_tab_entry.entry_data, 338 PORT_BRIDGEf, 0x1); 339 (void) soc_mem_write(unit, PORT_TABm, COPYNO_ALL, i, 340 port_tab_entry.entry_data); 341 } 342 } else { 343 cli_out("\n*ERROR, invalid mem %s\n", SOC_MEM_NAME(unit, PORT_TABm)); 344 } 345 } 346 347 /* 348 * Function: 349 * l3uc_lossless_flood_cnt 350 * Purpose: 351 * Calculates number of packets that need to be sent to a port for a 352 * lossless swirl. 353 * Parameters: 354 * unit - StrataSwitch Unit #. 355 * pkt_size : Packet size in bytes 356 * port: Test port no 357 * Returns: 358 * Number of packets needed for lossless flooding 359 */ 360 static uint32 361 l3uc_lossless_flood_cnt(int unit, int port) 362 { 363 uint32 pkt_size, flood_cnt = 0; 364 int param_flood_cnt, param_pkt_size; 365 l3uc_t *l3uc_p = l3uc_parray[unit]; 366 367 param_flood_cnt = l3uc_p->flood_pkt_cnt_param; 368 param_pkt_size = l3uc_p->pkt_size_param; 369 370 if (param_flood_cnt == 0) { 371 if (param_pkt_size == 0) { 372 pkt_size = stream_get_wc_pkt_size(unit, IS_HG_PORT(unit, port)); 373 } else { 374 pkt_size = param_pkt_size; 375 } 376 flood_cnt = stream_get_ll_flood_cnt(unit, port, pkt_size, NULL); 377 } else { 378 flood_cnt = param_flood_cnt; 379 } 380 381 return (flood_cnt); 382 } 383 384 /* 385 * Function: 386 * l3uc_set_up_streams 387 * Purpose: 388 * VLAN programming for l3uc. Each port is put on an unique VLAN. 389 * Parameters: 390 * unit: StrataSwitch Unit #. 391 * 392 * Returns: 393 * BCM_E_XXXX 394 */ 395 static bcm_error_t 396 l3uc_set_up_streams(int unit) 397 { 398 int p, j; 399 int src_port, dst_port; 400 int l2_id; 401 pbmp_t pbm, ubm; 402 bcm_l2_station_t l2_station; 403 bcm_l3_intf_t l3_intf; 404 bcm_l3_egress_t l3_egress; 405 bcm_if_t egr_obj_id; 406 bcm_l3_host_t l3_host; 407 bcm_field_qset_t f_qset; 408 bcm_field_group_t f_group; 409 bcm_field_entry_t f_entry; 410 l3uc_t *l3uc_p = l3uc_parray[unit]; 411 bcm_mac_t nhop_mac = MAC_DA; 412 bcm_mac_t router_mac = MAC_SA; 413 bcm_vlan_t vlan = VLAN; 414 bcm_ip_t ipv4_da = IPV4_ADDR; 415 bcm_ip6_t ipv6_da = IPV6_ADDR; 416 417 BCM_PBMP_CLEAR(ubm); 418 BCM_IF_ERROR_RETURN(bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 1)); 419 BCM_IF_ERROR_RETURN(bcm_port_control_set(unit, 0, bcmPortControlIP4, 1)); 420 BCM_IF_ERROR_RETURN(bcm_port_control_set(unit, 0, bcmPortControlIP6, 1)); 421 BCM_IF_ERROR_RETURN(bcm_field_init(unit)); 422 BCM_FIELD_QSET_INIT(f_qset); 423 BCM_FIELD_QSET_ADD(f_qset, bcmFieldQualifyOuterVlanId); 424 BCM_IF_ERROR_RETURN(bcm_field_group_create(unit, f_qset, 425 BCM_FIELD_GROUP_PRIO_ANY, 426 &f_group)); 427 428 PBMP_ITER(PBMP_E_ALL(unit), p) { 429 if (p < SOC_MAX_NUM_PORTS) { 430 src_port = p; 431 dst_port = l3uc_p->dst_port[p]; 432 nhop_mac[2] = dst_port; 433 router_mac[2] = src_port; 434 vlan = VLAN + src_port; 435 ipv4_da = IPV4_ADDR | (src_port << 8); 436 ipv6_da[14] = src_port; 437 438 /* Create VLAN */ 439 BCM_IF_ERROR_RETURN(bcm_vlan_create(unit, vlan)); 440 BCM_PBMP_CLEAR(pbm); 441 BCM_PBMP_PORT_ADD(pbm, src_port); 442 BCM_IF_ERROR_RETURN(bcm_vlan_port_add(unit, vlan, pbm, ubm)); 443 444 /* Add L2 Station */ 445 bcm_l2_station_t_init(&l2_station); 446 sal_memcpy(l2_station.dst_mac, nhop_mac, 6); 447 sal_memcpy(l2_station.dst_mac_mask, "ff:ff:ff:ff:ff:ff", 6); 448 l2_station.vlan = vlan; 449 l2_station.vlan_mask = 0xfff; 450 l2_station.flags |= BCM_L2_STATION_IPV4 | BCM_L2_STATION_IPV6; 451 BCM_IF_ERROR_RETURN(bcm_l2_station_add(unit, &l2_id, &l2_station)); 452 LOG_INFO(BSL_LS_APPL_TESTS, 453 (BSL_META_U(unit, "\nAdded L2 Station: "))); 454 LOG_INFO(BSL_LS_APPL_TESTS, 455 (BSL_META_U(unit, "mac %2x:%2x:%2x:%2x:%2x:%2x, vlan 0x%x"), 456 l2_station.dst_mac[5], l2_station.dst_mac[4], 457 l2_station.dst_mac[3], l2_station.dst_mac[2], 458 l2_station.dst_mac[1], l2_station.dst_mac[0], 459 l2_station.vlan)); 460 461 /* Create L3 Interfaces */ 462 bcm_l3_intf_t_init(&l3_intf); 463 l3_intf.l3a_flags |= BCM_L3_ADD_TO_ARL; 464 sal_memcpy(l3_intf.l3a_mac_addr, router_mac, 6); 465 l3_intf.l3a_vid = vlan; 466 BCM_IF_ERROR_RETURN(bcm_l3_intf_create(unit, &l3_intf)); 467 LOG_INFO(BSL_LS_APPL_TESTS, 468 (BSL_META_U(unit, "\nAdded L3 Interface: intf %0d, "), 469 l3_intf.l3a_intf_id)); 470 LOG_INFO(BSL_LS_APPL_TESTS, 471 (BSL_META_U(unit, "mac %2x:%2x:%2x:%2x:%2x:%2x, vlan 0x%x"), 472 l3_intf.l3a_mac_addr[5], l3_intf.l3a_mac_addr[4], 473 l3_intf.l3a_mac_addr[3], l3_intf.l3a_mac_addr[2], 474 l3_intf.l3a_mac_addr[1], l3_intf.l3a_mac_addr[0], 475 l3_intf.l3a_vid)); 476 477 /* Create Next Hop Egress Object */ 478 bcm_l3_egress_t_init(&l3_egress); 479 sal_memcpy(l3_egress.mac_addr, nhop_mac, 6); 480 l3_egress.intf = l3_intf.l3a_intf_id; 481 l3_egress.port = src_port; 482 BCM_IF_ERROR_RETURN(bcm_l3_egress_create(unit, 0, &l3_egress, 483 &egr_obj_id)); 484 LOG_INFO(BSL_LS_APPL_TESTS, 485 (BSL_META_U(unit, "\nAdded L3 Next Hop: nhop_id %0d, intf %0d, "), 486 egr_obj_id, l3_egress.intf)); 487 LOG_INFO(BSL_LS_APPL_TESTS, 488 (BSL_META_U(unit, "mac %2x:%2x:%2x:%2x:%2x:%2x, port %0d"), 489 l3_egress.mac_addr[5], l3_egress.mac_addr[4], 490 l3_egress.mac_addr[3], l3_egress.mac_addr[2], 491 l3_egress.mac_addr[1], l3_egress.mac_addr[0], 492 l3_egress.port)); 493 494 /* Associate IP Address with Egress Object */ 495 bcm_l3_host_t_init(&l3_host); 496 if (l3uc_p->ipv6_param) { 497 l3_host.l3a_flags = BCM_L3_IP6; 498 sal_memcpy(l3_host.l3a_ip6_addr, ipv6_da, 16); 499 } else { 500 l3_host.l3a_ip_addr = ipv4_da; 501 } 502 l3_host.l3a_intf = egr_obj_id; 503 BCM_IF_ERROR_RETURN(bcm_l3_host_add(unit, &l3_host)); 504 LOG_INFO(BSL_LS_APPL_TESTS, 505 (BSL_META_U(unit, "\nAdded L3 Table: nhop_id %0d, ip "), 506 egr_obj_id)); 507 if (l3uc_p->ipv6_param) { 508 for (j = 0; j < 16; j++) { 509 LOG_INFO(BSL_LS_APPL_TESTS, 510 (BSL_META_U(unit, "%0d."), 511 l3_host.l3a_ip6_addr[j])); 512 } 513 } else { 514 LOG_INFO(BSL_LS_APPL_TESTS, 515 (BSL_META_U(unit, "%0d.%0d.%0d.%0d"), 516 (l3_host.l3a_ip_addr) >> 24 & 0xff, 517 (l3_host.l3a_ip_addr) >> 16 & 0xff, 518 (l3_host.l3a_ip_addr) >> 8 & 0xff, 519 l3_host.l3a_ip_addr & 0xff)); 520 } 521 522 /* Program FP to L3 Switch */ 523 { 524 BCM_IF_ERROR_RETURN(bcm_field_entry_create(unit, f_group, &f_entry)); 525 BCM_IF_ERROR_RETURN(bcm_field_qualify_OuterVlanId(unit, f_entry, 526 VLAN + dst_port, 0xfff)); 527 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, f_entry, 528 bcmFieldActionL3Switch, 529 egr_obj_id, 0)); 530 BCM_IF_ERROR_RETURN(bcm_field_entry_install(unit, f_entry)); 531 LOG_INFO(BSL_LS_APPL_TESTS, 532 (BSL_META_U(unit, "\nAdded FP L3 Switch vlan 0x%x to "), 533 VLAN + dst_port)); 534 LOG_INFO(BSL_LS_APPL_TESTS, 535 (BSL_META_U(unit, "nhop_id %0d\n"), egr_obj_id)); 536 } 537 } 538 } 539 540 return BCM_E_NONE; 541 } 542 543 /* 544 * Function: 545 * l3uc_send_pkts 546 * Purpose: 547 * Send packets to flood VLANs and create a swirl on each port. 548 * Parameters: 549 * unit - StrataSwitch Unit #. 550 * 551 * Returns: 552 * Nothing 553 */ 554 static void 555 l3uc_send_pkts(int unit) 556 { 557 uint8 mac_da[] = MAC_DA; 558 uint8 mac_sa[] = MAC_SA; 559 int port, i = 0; 560 uint32 pkt_size = 0, pkt_count = 0, flood_cnt = 0; 561 uint8 src_port; 562 uint8 dst_port; 563 uint32 use_random_packet_sizes = 0; 564 l3uc_t *l3uc_p = l3uc_parray[unit]; 565 stream_pkt_t *tx_pkt; 566 567 tx_pkt = sal_alloc(sizeof(stream_pkt_t), "tx_pkt"); 568 sal_memset(tx_pkt, 0, sizeof(stream_pkt_t)); 569 570 if (l3uc_p->pkt_size_param == 1) { 571 use_random_packet_sizes = 1; 572 } 573 574 cli_out("\n==================================================\n"); 575 cli_out("\nSending packets ...\n\n"); 576 PBMP_ITER(PBMP_E_ALL(unit), port) { 577 if (port < SOC_MAX_NUM_PORTS) { 578 i++; 579 src_port = port; 580 dst_port = l3uc_p->dst_port[port]; 581 if (i % 2 == 0) { 582 flood_cnt = 0; 583 continue; 584 } else { 585 flood_cnt = l3uc_lossless_flood_cnt(unit, port); 586 } 587 588 if (l3uc_p->pkt_size_param == 0) { 589 pkt_size = stream_get_wc_pkt_size(unit, IS_HG_PORT(unit, port)); 590 } else { 591 pkt_size = l3uc_p->pkt_size_param; 592 } 593 594 tx_pkt->port = port; 595 tx_pkt->num_pkt = flood_cnt; 596 tx_pkt->pkt_seed = l3uc_p->pkt_seed + port; 597 tx_pkt->pkt_size = pkt_size; 598 tx_pkt->rand_pkt_size_en = use_random_packet_sizes; 599 tx_pkt->rand_pkt_size = NULL; 600 tx_pkt->tx_vlan = VLAN + src_port; 601 sal_memcpy(tx_pkt->mac_da, mac_da, NUM_BYTES_MAC_ADDR); 602 sal_memcpy(tx_pkt->mac_sa, mac_sa, NUM_BYTES_MAC_ADDR); 603 tx_pkt->mac_da[2] = dst_port; 604 tx_pkt->mac_sa[2] = src_port; 605 if (tx_pkt->rand_pkt_size_en) { 606 tx_pkt->rand_pkt_size = l3uc_p->rand_pkt_sizes[port]; 607 } 608 tx_pkt->l3_en = 1; 609 tx_pkt->ipv6_en = l3uc_p->ipv6_param; 610 tx_pkt->ip_da = IPV4_ADDR | (dst_port << 8); 611 tx_pkt->ip_sa = IPV4_ADDR | (src_port << 8); 612 tx_pkt->ttl = TTL; 613 stream_tx_pkt(unit, tx_pkt); 614 615 /* print */ 616 cli_out("flood_cnt for stream %0d = %0d\n", i/2, tx_pkt->cnt_pkt); 617 pkt_count += tx_pkt->cnt_pkt; 618 } 619 } 620 cli_out("\nTotal packet sent: %d\n\n", pkt_count); 621 sal_free(tx_pkt); 622 } 623 624 /* 625 * Function: 626 * l3uc_chk_port_rate 627 * Purpose: 628 * Check actual port rates against expected port rates. 629 * Parameters: 630 * unit - StrataSwitch Unit #. 631 * 632 * Returns: 633 * SOC_E_XXXX 634 */ 635 static bcm_error_t 636 l3uc_chk_port_rate(int unit) 637 { 638 int port; 639 bcm_error_t rv = BCM_E_NONE; 640 stream_rate_t *rate_calc; 641 l3uc_t *l3uc_p = l3uc_parray[unit]; 642 643 rate_calc = (stream_rate_t *) 644 sal_alloc(sizeof(stream_rate_t), "rate_calc"); 645 if (rate_calc == NULL) { 646 test_error(unit, "Failed to allocate memory for rate_calc\n"); 647 return BCM_E_FAIL; 648 } 649 sal_memset(rate_calc, 0, sizeof(stream_rate_t)); 650 651 rate_calc->mode = 0; /* check act_rate against config_rate */ 652 rate_calc->pkt_size = l3uc_p->pkt_size_param; 653 rate_calc->interval_len = l3uc_p->rate_calc_interval_param; 654 rate_calc->tolerance_lr = l3uc_p->rate_tolerance_lr_param; 655 rate_calc->tolerance_os = l3uc_p->rate_tolerance_ov_param; 656 rate_calc->scaling_factor = l3uc_p->scaling_factor_param; 657 658 SOC_PBMP_CLEAR(rate_calc->pbmp); 659 PBMP_ITER(PBMP_E_ALL(unit), port) { 660 if (port < SOC_MAX_NUM_PORTS) { 661 SOC_PBMP_PORT_ADD(rate_calc->pbmp, port); 662 } 663 } 664 665 rv = stream_chk_port_rate(unit, PBMP_PORT_ALL(unit), rate_calc); 666 667 sal_free(rate_calc); 668 return rv; 669 } 670 671 /* 672 * Function: 673 * l3uc_chk_pkt_integrity 674 * Purpose: 675 * Redirect all packets back to CPU and check packet integrity 676 * Parameters: 677 * unit - StrataSwitch Unit #. 678 * 679 * Returns: 680 * Nothing 681 */ 682 static bcm_error_t 683 l3uc_chk_pkt_integrity(int unit) 684 { 685 int idx = 0, port, dst_port, src_port, is_even; 686 int param_pkt_seed; 687 uint32 flood_cnt; 688 uint8 mac_da[] = MAC_DA; 689 uint8 mac_sa[] = MAC_SA; 690 stream_integrity_t *pkt_intg; 691 bcm_error_t rv = BCM_E_NONE; 692 l3uc_t *l3uc_p = l3uc_parray[unit]; 693 694 param_pkt_seed = l3uc_p->pkt_seed; 695 696 pkt_intg = sal_alloc(sizeof(stream_integrity_t), "pkt_intg"); 697 if (pkt_intg == NULL) { 698 test_error(unit, "Failed to allocate memory for pkt_intg\n"); 699 return BCM_E_FAIL; 700 } 701 sal_memset(pkt_intg, 0, sizeof(stream_integrity_t)); 702 703 pkt_intg->type = PKT_TYPE_L3UC; 704 pkt_intg->ipv6_en = (l3uc_p->ipv6_param > 0) ? 1 : 0; 705 SOC_PBMP_CLEAR(pkt_intg->rx_pbmp); 706 PBMP_ITER(PBMP_E_ALL(unit), port) { 707 if (port < SOC_MAX_NUM_PORTS) { 708 is_even = (idx % 2 == 0) ? (1) : (0); 709 src_port = port; 710 dst_port = l3uc_p->dst_port[port]; 711 /* rx_pbmp */ 712 if (is_even == 1) { 713 SOC_PBMP_PORT_ADD(pkt_intg->rx_pbmp, port); 714 } 715 /* rx_vlan: used to forward pkt to CPU */ 716 pkt_intg->rx_vlan[port] = VLAN + dst_port; 717 /* tx_vlan: used to re-generate ref_pkt */ 718 pkt_intg->tx_vlan[port] = VLAN + src_port; 719 /* port_flood_cnt */ 720 if (is_even) { 721 flood_cnt = l3uc_lossless_flood_cnt(unit, port); 722 } else { 723 flood_cnt = 0; 724 } 725 pkt_intg->port_flood_cnt[port] = flood_cnt; 726 /* port_pkt_seed */ 727 pkt_intg->port_pkt_seed[port] = param_pkt_seed + port; 728 /* mac_da, mac_sa */ 729 mac_da[2] = dst_port; 730 mac_sa[2] = src_port; 731 sal_memcpy(pkt_intg->mac_da[port], mac_da, NUM_BYTES_MAC_ADDR); 732 sal_memcpy(pkt_intg->mac_sa[port], mac_sa, NUM_BYTES_MAC_ADDR); 733 /* ip_da, ip_sa */ 734 pkt_intg->ip_da[port] = IPV4_ADDR | (dst_port << 8); 735 pkt_intg->ip_sa[port] = IPV4_ADDR | (src_port << 8); 736 737 idx++; 738 } 739 } 740 741 if (stream_chk_pkt_integrity(unit, pkt_intg) != BCM_E_NONE) { 742 rv = BCM_E_FAIL; 743 } 744 745 sal_free(pkt_intg); 746 return rv; 747 } 748 749 /* 750 * Function: 751 * l3uc_test_init 752 * Purpose: 753 * Test init function. Parse CLI params and do necessary init. 754 * Parameters: 755 * unit - StrataSwitch Unit #. 756 * 757 * Returns: 758 * Nothing 759 */ 760 int 761 l3uc_test_init(int unit, args_t *a, void **pa) 762 { 763 int i, p, src_port; 764 l3uc_t *l3uc_p; 765 766 l3uc_p = l3uc_parray[unit]; 767 l3uc_p = sal_alloc(sizeof(l3uc_t), "l3uc_test"); 768 sal_memset(l3uc_p, 0, sizeof(l3uc_t)); 769 l3uc_parray[unit] = l3uc_p; 770 771 cli_out("\nCalling l3uc_test_init"); 772 l3uc_parse_test_params(unit, a); 773 774 for (p = 0; p < SOC_MAX_NUM_PORTS; p++) { 775 l3uc_p->dst_port[p] = 0; 776 } 777 778 i = 0; 779 src_port = 0; 780 PBMP_ITER(PBMP_E_ALL(unit), p) { 781 if (p < SOC_MAX_NUM_PORTS) { 782 if (i % 2 == 0) { 783 src_port = p; 784 } else { 785 l3uc_p->dst_port[src_port] = p; 786 l3uc_p->dst_port[p] = src_port; 787 } 788 i++; 789 } 790 } 791 792 l3uc_p->test_fail = 0; 793 794 return BCM_E_NONE; 795 } 796 797 798 /* 799 * Function: 800 * l3uc_test 801 * Purpose: 802 * Set up ports/streams and send packets. 803 * Parameters: 804 * unit - StrataSwitch Unit #. 805 * 806 * Returns: 807 * Nothing 808 */ 809 int 810 l3uc_test(int unit, args_t *a, void *pa) 811 { 812 int rv = BCM_E_NONE; 813 l3uc_t *l3uc_p = l3uc_parray[unit]; 814 815 if (l3uc_p->bad_input) { 816 goto done; 817 } 818 819 cli_out("\nCalling l3uc_test"); 820 821 stream_set_lpbk(unit, PBMP_PORT_ALL(unit), l3uc_p->loopback_mode_param); 822 stream_turn_off_cmic_mmu_bkp(unit); 823 stream_turn_off_fc(unit, PBMP_PORT_ALL(unit)); 824 l3uc_p->pkt_seed = sal_rand(); 825 l3uc_set_port_property(unit, PBMP_PORT_ALL(unit), l3uc_p->pkt_size_param, 826 l3uc_p->max_num_cells_param); 827 l3uc_set_up_ports(unit, PBMP_PORT_ALL(unit)); 828 l3uc_set_up_streams(unit); 829 l3uc_send_pkts(unit); 830 831 /* check counter */ 832 if (stream_chk_mib_counters(unit, PBMP_PORT_ALL(unit), 0) != BCM_E_NONE) { 833 l3uc_p->test_fail = 1; 834 } 835 /* check rate */ 836 if (l3uc_chk_port_rate(unit) != BCM_E_NONE) { 837 l3uc_p->test_fail = 1; 838 } 839 /* check integrity */ 840 if (l3uc_chk_pkt_integrity(unit) != BCM_E_NONE) { 841 l3uc_p->test_fail = 1; 842 } 843 844 845 done: 846 return rv; 847 } 848 849 850 /* 851 * Function: 852 * l3uc_test_cleanup 853 * Purpose: 854 * Do test end checks and free all allocated memory. 855 * Parameters: 856 * unit - StrataSwitch Unit #. 857 * 858 * Returns: 859 * Nothing 860 */ 861 int 862 l3uc_test_cleanup(int unit, void *pa) 863 { 864 int i; 865 bcm_error_t rv = BCM_E_NONE; 866 l3uc_t *l3uc_p = l3uc_parray[unit]; 867 868 cli_out("\nCalling l3uc_test_cleanup"); 869 870 if (l3uc_p->bad_input == 1) { 871 l3uc_p->test_fail = 1; 872 } 873 if (l3uc_p->test_fail == 1) { 874 rv = BCM_E_FAIL; 875 } 876 877 cli_out("\n=================================================="); 878 cli_out("\n=================================================="); 879 if (l3uc_p->test_fail == 1) { 880 cli_out("\n[L3UC test failed]\n\n"); 881 } else { 882 cli_out("\n[L3UC test passed]\n\n"); 883 } 884 885 /* free mem */ 886 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 887 sal_free(l3uc_p->rand_pkt_sizes[i]); 888 } 889 sal_free(l3uc_p->rand_pkt_sizes); 890 sal_free(l3uc_p); 891 bcm_vlan_init(unit); 892 return rv; 893 } 894 #endif /* BCM_ESW_SUPPORT && INCLUDE_L3 */