tpacket.c (44482B)
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 * Packet tests that use the BCM api. 8 */ 9 10 #include <sal/types.h> 11 #include <sal/core/time.h> 12 #include <sal/core/stats.h> 13 #include <sal/appl/sal.h> 14 #include <shared/bsl.h> 15 #include <soc/util.h> 16 #include <shared/bsl.h> 17 #include <appl/diag/system.h> 18 #include <appl/diag/parse.h> 19 20 #include <bcm/error.h> 21 #include <bcm/l2.h> 22 #include <bcm/mcast.h> 23 #include <bcm/pkt.h> 24 #include <bcm/tx.h> 25 #include <bcm/rx.h> 26 27 28 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 29 30 #include <bcm/knet.h> 31 #include <errno.h> 32 #include <stdio.h> 33 #include <unistd.h> 34 #include <arpa/inet.h> 35 #include <sys/socket.h> 36 #include <linux/if_ether.h> 37 #include <linux/if_packet.h> 38 #include <linux/if.h> 39 #include <sys/ioctl.h> 40 #include <sys/poll.h> 41 #include <sys/mman.h> 42 43 #include <sched.h> 44 #include <sal/core/thread.h> 45 #endif 46 47 #ifdef BCM_PETRA_SUPPORT 48 #include <soc/dpp/drv.h> 49 #include <soc/dpp/port_sw_db.h> 50 #endif 51 52 #include "testlist.h" 53 54 #define xstr(a) str(a) 55 #define str(a) #a 56 57 #define PACKET_MAX_BUFFER (16 * 1024) /* 16K max packet */ 58 59 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 60 static uint8 tp_ptch_header[2] = {0xd0, 0x00}; 61 #endif 62 #ifdef BCM_DNX_SUPPORT 63 static uint8 tp_mh_header[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 64 #endif 65 66 char tr40_test_usage[] = 67 "TR40 (send packets) Usage:\n" 68 " \n" 69 #ifdef COMPILER_STRING_CONST_LIMIT 70 "\nFull documentation cannot be displayed with -pendantic compiler\n"; 71 #else 72 "Tagged=<true/false> - Specifies Tagged flag (true) or not tagged (false) in tx descriptor\n" 73 "VlanId=<value> - Specifies Vlad Id \n" 74 "TpId=<value> - Specifies Type ID. Default: '0x8100'\n" 75 "LengthStart=<value> - Specifies Length Start value (first tx packet length in a chain) <=" xstr(PACKET_MAX_BUFFER) "\n" 76 "LengthEnd=<value> - Specifies length End value (max tx packet length in a current chain) <=" xstr(PACKET_MAX_BUFFER) "\n" 77 "LengthInc=<value> - Specifies length increment value in n-packet in a current chain, current (n) packet lenght = length start + n * lenght increment \n" 78 "PktsPerChain=<value> - Specifies number of packet will be sent in current chain starts from LengthStart, packet length is incrementing by LengthInc till LengthEnd \n" 79 "Chains=<value> - Specifies number of chains will be sent (each chain includes PktsPerChain packets \n" 80 "Array=<true/false> - Specifies if chain (>1 packets) will be sent by array (bcm_tx_array) or by list (bcm_tx_list)\n" 81 "Operations<1<value<1000> - Specifies loop number to run of chains\n" 82 "HIGig=<true/false> - Specifies Higig flag (true) or not mark (false) in tx descriptor\n" 83 "PURge=<true/false> - Specifies Purge flag (true) or not mark (false) in tx descriptor\n" 84 "CHNUMber=<value> - Specifies descriptor channel number (from 0 to 255), 0 by default\n" 85 "MacDest=<xx:xx:xx:xx:xx:xx> - Specifies Destination Mac address\n" 86 "MacSrc=<xx:xx:xx:xx:xx:xx> - Specifies Source Mac address\n" 87 "Pattern=<0xvalue> - Specifies a pattern to use in packet payload(usefile=false)\n" 88 "PatternInc=<value> - Specifies a packet increment pattern value (pattern + patterninc) uses in packet payload (usefile=false)\n" 89 "PatternRandom=<true/false> - Creates random parrern in packet payload (usefile=false)\n" 90 "Filename=<name string> - Specifies file name when file is in use (usefile=true)\n" 91 "FileLen=<value> - Specifies file length when file is in use (usefile=true)\n" 92 "UseFile=<true/false> - Marks if file is used for packet send(true) or via build-in procedure \n" 93 "\n" 94 ; 95 #endif /*COMPILER_STRING_CONST_LIMIT*/ 96 97 98 #define XD_FILE(xd) ((xd)->xd_file != NULL && (xd)->xd_file[0] != 0) 99 100 STATIC int8 tx_load_packet_tr(int unit, char *fname, int length, uint8 *packet_in); 101 102 typedef struct p_s { 103 int p_init; /* TRUE --> initialized */ 104 int p_opt; /* Destination option */ 105 # define P_O_UC_HIT 0 /* Unicast in ARL */ 106 # define P_O_UC_MISS 1 /* Unicast not in ARL */ 107 # define P_O_MC_HIT 2 /* L2 multicast in MARL/L2 */ 108 # define P_O_MC_MISS 3 /* L2 multicast not in MARL/L2 */ 109 # define P_O_BC 4 /* L2 Broadcast */ 110 # define P_O_PORT 5 /* Send to specific ports */ 111 # define P_O_DPP_PORT 6 /* Send to specific dpp */ 112 113 int p_fp; /* TRUE --> Use fastpath (new only) */ 114 int p_tag; /* TRUE --> tag packet */ 115 int p_vid; /* VLAN id if tagged */ 116 int p_tpid; 117 sal_mac_addr_t p_dst; /* Dest mac address */ 118 sal_mac_addr_t p_src; /* Source mac address */ 119 int p_array; /* Array? Bool; false -> list */ 120 int ppc; /* # packets per chain */ 121 int chains; /* # chains */ 122 int p_cnt_start; /* # started */ 123 volatile int chains_done; /* # complete */ 124 int p_cnt_accum; /* Accumulated q length all samples */ 125 pbmp_t p_pbm; /* Ports to xmit on */ 126 pbmp_t p_upbm; /* Untabg ports (only if fast) */ 127 int len_start; /* Length start */ 128 int len_end; /* Length end */ 129 int p_l_inc; /* Length increment */ 130 int p_ops; /* # outstanding operations */ 131 sal_sem_t p_sem_active; /* Synchronize # active */ 132 sal_sem_t p_sem_done; /* Completion wait */ 133 int p_ops_total; /* Accumulated operations outstanding */ 134 enet_hdr_t *p_tx; /* Tx - Packet buffer */ 135 bcm_pkt_t *p_pkt; /* The packet being tx'd */ 136 bcm_pkt_t **p_pkt_array; /* Array of pkt pointers */ 137 char test_usage[20]; 138 uint32 xd_pat; 139 uint32 xd_pat_inc; 140 uint32 xd_pat_random; 141 char *xd_file; /* File name of packet data */ 142 uint32 xd_filelen; /* File length to get*/ 143 int xd_usefile; /* Flag indicates that just a file is in use for test*/ 144 uint32 purge_flag; 145 uint32 higig_flag; 146 int ch_number; 147 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 148 int p_use_socket; 149 int p_sock; 150 int p_netid; 151 int p_filterid; 152 #endif 153 int p_sync; 154 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 155 int p_ptch_source_port; 156 #endif 157 } p_t; 158 159 static sal_mac_addr_t tp_mac_uc = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; 160 static sal_mac_addr_t tp_mac_mc = {0x01, 0x11, 0x22, 0x33, 0x44, 0x44}; 161 static sal_mac_addr_t tp_mac_bc = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 162 163 static sal_mac_addr_t tp_mac_dpp_src = {0x00, 0x00, 0x00, 0x00, 0x00, 0xe2}; 164 static sal_mac_addr_t tp_mac_dpp_dst = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; 165 166 167 static sal_mac_addr_t tp_mac_empty = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 168 169 static uint8 mypacket[] = { 170 0x1,0x2, 171 0x7,0x8,0x9,0xa, 172 0xb,0xc,0xd,0xe, 0xf,0x10,0x11,0x12, 173 174 0x13,0x14,0x15,0x16, 0x17,0x18,0x19,0x1a, 175 0x1b,0x1c,0x1d,0x1e, 0x1f,0x20,0x21,0x22, 176 177 0x23,0x24,0x25,0x26, 0x27,0x28,0x29,0x2a, 178 0x2b,0x2c,0x2d,0x2e, 0x2f,0x30,0x31,0x32, 179 180 0x33,0x34,0x35,0x36, 0x37,0x38,0x39,0x3a, 181 0x3b,0x3c,0x3d,0x3e, 0x3f,0x40,0x41,0x42, 182 183 0x43,0x44,0x45,0x46, 0x47,0x48,0x49,0x4a, 184 0x4b,0x4c,0x4d,0x4e, 0x4f,0x50,0x51,0x52, 185 186 187 0x53,0x54,0x55,0x56, 0x57,0x58,0x59,0x5a, 188 0x5b,0x5c,0x5d,0x5e, 0x5f,0x60,0x61,0x62, 189 190 0x63,0x64,0x65,0x66, 0x67,0x68,0x69,0x6a, 191 0x6b,0x6c,0x6d,0x6e, 0x6f,0x70,0x71,0x72, 192 193 0x73,0x74,0x75,0x76, 0x77,0x78,0x79,0x7a, 194 0x7b,0x7c,0x7d,0x7e, 0x7f,0x80,0x81,0x82 }; 195 196 static p_t *p_control[SOC_MAX_NUM_DEVICES]; 197 198 /** Define length of Module Header */ 199 #ifndef DNX_MODULE_HEADER_SIZE 200 #if defined(BCM_DNX_SUPPORT) && !defined(ADAPTER_SERVER_MODE) 201 /** Size of module header on DNX devices, it should be written at the start of the packet */ 202 #define DNX_MODULE_HEADER_SIZE 16 203 #else 204 /** No Module Header on ADAPTER and non DNX*/ 205 #define DNX_MODULE_HEADER_SIZE 0 206 #endif 207 #endif 208 209 #ifdef BCM_DNX_SUPPORT 210 /** Define length PTCH-2 */ 211 #define TP_DNX_HDR_PTCH_TYPE2_LEN 2 212 #define TP_DNX_MAC_ADDR_LEN 6 213 214 /* Helper macro for appending Module Header to ethernet packets */ 215 #define TP_DNX_PKT_MH_HDR_SET(pkt, mh) \ 216 sal_memcpy((pkt)->_pkt_data.data, (mh), DNX_MODULE_HEADER_SIZE) 217 218 /* Helper macro for appending PTCH2 header to ethernet packets with Module Header */ 219 #define TP_DNX_PKT_PTCH_HDR_SET_WITH_MH(pkt, ptch) \ 220 sal_memcpy((pkt)->_pkt_data.data + DNX_MODULE_HEADER_SIZE, (ptch), TP_DNX_HDR_PTCH_TYPE2_LEN) 221 222 /* Helper macro for setting DMAC to ethernet packets with Module Header and PTCH2 header */ 223 #define TP_DNX_PKT_HDR_DMAC_SET_WITH_MH_PTCH(pkt, dmac) \ 224 sal_memcpy((pkt)->_pkt_data.data + DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN, (dmac), TP_DNX_MAC_ADDR_LEN) 225 226 /* Helper macro for setting SMAC to ethernet packets with Module Header and PTCH2 header */ 227 #define TP_DNX_PKT_HDR_SMAC_SET_WITH_MH_PTCH(pkt, smac) \ 228 sal_memcpy((pkt)->_pkt_data.data + DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN + 6, (smac), TP_DNX_MAC_ADDR_LEN) 229 230 /* Helper macro for setting uint16 to specified position of packet val in network byte order */ 231 #define TP_DNX_HTONS_CVT_SET(pkt, val, posn) \ 232 do { \ 233 uint16 _tmp; \ 234 _tmp = soc_htons(val); \ 235 sal_memcpy((pkt)->_pkt_data.data + (posn), &_tmp, sizeof(uint16)); \ 236 } while (0) 237 238 /* Helper macro for setting TPID to ethernet packets with Module Header and PTCH header */ 239 #define TP_DNX_PKT_HDR_TPID_SET_WITH_MH_PTCH(pkt, tpid) \ 240 TP_DNX_HTONS_CVT_SET(pkt, tpid, DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN + TP_DNX_MAC_ADDR_LEN + TP_DNX_MAC_ADDR_LEN) 241 242 /* Helper macro for setting vlan tag to ethernet packets with Module Header and PTCH header */ 243 #define TP_DNX_PKT_HDR_VTAG_CONTROL_SET_WITH_MH_PTCH(pkt, vtag) \ 244 TP_DNX_HTONS_CVT_SET(pkt, vtag, DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN + TP_DNX_MAC_ADDR_LEN + TP_DNX_MAC_ADDR_LEN + sizeof(uint16)) 245 246 /* Helper macro for single buffer Ethernet packet with PTCH header(not HiGig). */ 247 #define TP_DNX_PKT_HDR_TAGGED_LEN_SET_WITH_MH_PTCH(pkt, len) \ 248 TP_DNX_HTONS_CVT_SET(pkt, len, DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN + TP_DNX_MAC_ADDR_LEN + TP_DNX_MAC_ADDR_LEN + sizeof(uint32)) 249 #endif 250 251 extern int bcm_common_tx(int unit, bcm_pkt_t *pkt, void *cookie); 252 253 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 254 255 STATIC int 256 tx_bind_device(int sock, char* dev) 257 { 258 int rv; 259 struct sockaddr_ll addr; 260 struct ifreq req; 261 262 263 sal_memset(&req, 0, sizeof(req)); 264 sal_strncpy(req.ifr_name, dev, sizeof(req.ifr_name)); 265 if ((rv = ioctl(sock, SIOCGIFINDEX, &req)) < 0) { 266 cli_out("ioctl error %d\n", errno); 267 return rv; 268 } 269 270 if ((rv = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, 271 (void *)&req, sizeof(req))) < 0) { 272 cli_out("bind_device setsockopt error %d\n", errno); 273 return rv; 274 } 275 276 sal_memset(&addr, 0, sizeof(addr)); 277 addr.sll_family = AF_PACKET; 278 addr.sll_protocol = htons(0x8100); 279 addr.sll_ifindex = req.ifr_ifindex; 280 addr.sll_hatype = 0; 281 addr.sll_pkttype = 0; 282 addr.sll_halen = 0; 283 if ((rv = bind(sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) { 284 cli_out("bind error %d\n", errno); 285 return rv; 286 } 287 return 0; 288 } 289 290 STATIC int 291 tx_set_promisc_up(int sock, char* dev) 292 { 293 struct ifreq req; 294 sal_strncpy(req.ifr_name, dev, sizeof(req.ifr_name)); 295 296 if (ioctl(sock, SIOCGIFFLAGS, &req)==-1) { 297 cli_out("ioctl error"); 298 return -1; 299 } 300 req.ifr_flags |= (IFF_PROMISC | IFF_UP | IFF_RUNNING); 301 if (ioctl(sock, SIOCSIFFLAGS, &req)==-1) { 302 cli_out("ioctl error"); 303 return -1; 304 } 305 return 0; 306 } 307 308 STATIC int 309 tx_knetif_setup(int unit, p_t *p) 310 { 311 int rv; 312 313 bcm_knet_netif_t netif; 314 bcm_knet_filter_t filter; 315 316 bcm_knet_netif_t_init(&netif); 317 netif.type = BCM_KNET_NETIF_T_TX_CPU_INGRESS; 318 sal_memcpy(netif.mac_addr, tp_mac_uc, 6); 319 320 p->p_netid = 0; 321 rv = bcm_knet_netif_create(unit, &netif); 322 if (BCM_SUCCESS(rv)) { 323 p->p_netid = netif.id; 324 } else { 325 cli_out("bcm_knet_netif_create failed: %d\n", rv); 326 return rv; 327 } 328 329 p->p_filterid = 0; 330 bcm_knet_filter_t_init(&filter); 331 filter.type = BCM_KNET_FILTER_T_RX_PKT; 332 if (p->p_use_socket) { 333 filter.dest_type = BCM_KNET_DEST_T_NETIF; 334 filter.dest_id = p->p_netid; 335 } else { 336 filter.dest_type = BCM_KNET_DEST_T_BCM_RX_API; 337 } 338 rv = bcm_knet_filter_create(unit, &filter); 339 if (BCM_SUCCESS(rv)) { 340 p->p_filterid = filter.id; 341 } else { 342 cli_out("bcm_knet_filter_create:%d\n", rv); 343 return rv; 344 } 345 346 p->p_sock = socket(AF_PACKET, SOCK_RAW, htons(0x8100)); 347 348 tx_set_promisc_up(p->p_sock, "bcm0"); 349 tx_set_promisc_up(p->p_sock, netif.name); 350 351 tx_bind_device(p->p_sock, netif.name); 352 353 return rv; 354 } 355 356 357 STATIC void 358 tx_knetif_clean(int unit, p_t *p) 359 { 360 361 if (p->p_sock > 0) { 362 struct ifreq req; 363 bcm_knet_netif_t netif; 364 bcm_knet_netif_get(unit, p->p_netid, &netif); 365 366 sal_strncpy(req.ifr_name, netif.name, sizeof(req.ifr_name)); 367 368 if (ioctl(p->p_sock, SIOCGIFFLAGS, &req)==-1) { 369 cli_out("ioctl SIOCGIFFLAGS error"); 370 } 371 req.ifr_flags &= (~(IFF_UP | IFF_RUNNING)); 372 if (ioctl(p->p_sock, SIOCSIFFLAGS, &req)==-1) { 373 cli_out("ioctl SIOCSIFFLAGS error"); 374 } 375 close(p->p_sock); 376 p->p_sock = 0; 377 } 378 if (p->p_filterid > 0) { 379 bcm_knet_filter_destroy(unit, p->p_filterid); 380 p->p_filterid = 0; 381 } 382 383 if (p->p_netid > 0) { 384 bcm_knet_netif_destroy(unit, p->p_netid); 385 p->p_netid = 0; 386 } 387 } 388 389 #endif 390 391 /* */ 392 STATIC enet_hdr_t * 393 tpacket_get_enet_hdr(int unit, bcm_pkt_t *pkt) 394 { 395 enet_hdr_t *enet_hdr; 396 397 #ifdef BCM_PETRA_SUPPORT 398 if (SOC_IS_ARAD(unit)) { 399 enet_hdr = (enet_hdr_t *)(BCM_PKT_DMAC(pkt) + 2); 400 } 401 else 402 #endif 403 #if defined (BCM_DNX_SUPPORT) 404 if (SOC_IS_DNX(unit)) 405 { 406 enet_hdr = (enet_hdr_t *)(BCM_PKT_DMAC(pkt) + DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN); 407 } 408 else 409 #endif 410 { 411 enet_hdr = (enet_hdr_t *)BCM_PKT_DMAC(pkt); 412 } 413 414 return enet_hdr; 415 } 416 417 STATIC void 418 xmit_chain_done(int unit, bcm_pkt_t *pkt, void *cookie) 419 { 420 p_t *p = (p_t *)cookie; 421 422 sal_sem_give(p->p_sem_active); /* Allow next */ 423 if (++p->chains_done == p->chains) { 424 sal_sem_give(p->p_sem_done); 425 } 426 } 427 428 /* Note: i != 0, at least not for linked lists */ 429 #define PKT_PTR_NEXT(p, i, cur) (((p)->ppc > 1) ? \ 430 ((p)->p_array ? (p)->p_pkt_array[i] : (cur)->next) : NULL) 431 432 #define FOREACH_P_PKT(p, i, pkt) \ 433 for ((i) = 0, (pkt) = (p)->p_pkt; (i) < (p)->ppc; \ 434 (i)++, (pkt) = PKT_PTR_NEXT(p, i, pkt)) 435 436 437 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 438 static int 439 tp_dune_get_ssp_and_cpu_channel(int unit, bcm_pkt_t *pkt, p_t *p) 440 { 441 int rv = BCM_E_NONE; 442 443 #ifdef BCM_DNX_SUPPORT 444 if (SOC_IS_DNX(unit)) 445 { 446 uint32 flags; 447 bcm_port_interface_info_t interface_info; 448 bcm_port_mapping_info_t mapping_info; 449 450 rv = bcm_port_get(unit, p->p_ptch_source_port, &flags, &interface_info, &mapping_info); 451 if (rv != BCM_E_NONE) 452 { 453 test_error(unit, "bcm_port_get failed: %s\n", bcm_errmsg(rv)); 454 } 455 /* J2C has 1024 ports, in_pp_port takes 2 bits of "Reserved" field and 8 bits "In-PP-Port" field */ 456 tp_ptch_header[0] = (0xd0 | ((mapping_info.pp_port >> 8) & 0x3)); 457 tp_ptch_header[1] = mapping_info.pp_port & 0xff; 458 459 if (p->ch_number) 460 { 461 /* Use configured ch */ 462 pkt->_dpp_hdr[0] = p->ch_number & 0xff; 463 } 464 else 465 { 466 /* CPU channel will be set to first byte of Module Header */ 467 pkt->_dpp_hdr[0] = mapping_info.channel & 0xff; 468 } 469 } 470 #endif 471 #ifdef BCM_PETRA_SUPPORT 472 if (SOC_IS_ARAD(unit)) 473 { 474 uint32 pp_port; 475 uint32 tm_port; 476 uint32 channel; 477 int core; 478 479 rv = soc_port_sw_db_local_to_pp_port_get(unit, p->p_ptch_source_port, &pp_port, &core); 480 if (rv != BCM_E_NONE) 481 { 482 test_error(unit, "soc_port_sw_db_local_to_pp_port_get failed: %s\n", bcm_errmsg(rv)); 483 } 484 tp_ptch_header[1] = pp_port & 0xff; 485 486 if (p->ch_number) 487 { 488 /* 489 * Use configured ch, there is no guarantee that packets will be discarded 490 * If packets are forwarded to CPU ports, tx performance is degraded because it takes time to handle RX interrupts 491 */ 492 pkt->_dpp_hdr[0] = (uint32)p->ch_number; 493 } 494 else 495 { 496 rv = soc_port_sw_db_local_to_tm_port_get(unit, p->p_ptch_source_port, &tm_port, &core); 497 if (rv != BCM_E_NONE) 498 { 499 test_error(unit, "soc_port_sw_db_local_to_pp_port_get failed: %s\n", bcm_errmsg(rv)); 500 } 501 rv = soc_port_sw_db_channel_get(unit, tm_port, &channel); 502 if (rv != BCM_E_NONE) 503 { 504 test_error(unit, "soc_port_sw_db_channel_get failed: %s\n", bcm_errmsg(rv)); 505 } 506 pkt->_dpp_hdr[0] = channel & 0xff; 507 } 508 509 } 510 #endif 511 /** Always set BCM_PKT_F_HGHDR to indicate MH is present*/ 512 pkt->flags |= BCM_PKT_F_HGHDR; 513 514 pkt->_dpp_hdr[1] = 0; 515 pkt->_dpp_hdr[2] = 0; 516 pkt->_dpp_hdr[3] = 0; 517 518 return rv; 519 } 520 #endif 521 522 STATIC int 523 tpacket_setup(int unit, p_t *p) 524 { 525 enet_hdr_t *enet_hdr; 526 uint8 *fill_addr; 527 bcm_pkt_t *pkt; 528 int i; 529 530 p->p_sem_active = sal_sem_create("tpacket_ops", 531 sal_sem_COUNTING, 532 p->p_ops); 533 p->p_sem_done = sal_sem_create("tpacket_done", 534 sal_sem_BINARY, 535 0); 536 537 if ((p->p_sem_active == NULL)) { 538 test_error(unit, "Failed to allocate p_sem_active Tx Buffer\n"); 539 return(-1); 540 } 541 if ( (p->p_sem_done == NULL)) { 542 test_error(unit, "Failed to allocate p_sem_done Tx Buffer\n"); 543 return(-1); 544 } 545 546 #ifdef BCM_PETRA_SUPPORT 547 if (SOC_IS_ARAD(unit)) 548 { 549 /* DPP keeps configured ppc */ 550 } 551 else 552 #endif 553 #ifdef BCM_DNX_SUPPORT 554 if (SOC_IS_DNX(unit)) 555 { 556 /* DNX keeps configured ppc */ 557 } 558 else 559 #endif 560 { 561 if (soc_feature(unit, soc_feature_cmicx)) { 562 p->ppc = 1; 563 } 564 } 565 566 if (p->ppc > 1) { /* Multiple packets per chain */ 567 if (p->p_array) { 568 bcm_pkt_blk_alloc(unit, p->ppc, 569 PACKET_MAX_BUFFER, BCM_TX_CRC_REGEN, 570 &(p->p_pkt_array)); 571 if (!p->p_pkt_array) { 572 test_error(unit, "Failed to allocate pkt array\n"); 573 return -1; 574 } 575 p->p_pkt = p->p_pkt_array[0]; 576 } else { /* Linked list */ 577 for (i = 0; i < p->ppc; i++) { 578 bcm_pkt_alloc(unit, PACKET_MAX_BUFFER, 579 BCM_TX_CRC_REGEN, &pkt); 580 if (!pkt) { 581 test_error(unit, "Failed to allocate pkt list\n"); 582 return -1; 583 } 584 pkt->next = p->p_pkt; 585 p->p_pkt = pkt; 586 } 587 } 588 } else { 589 bcm_pkt_alloc(unit, PACKET_MAX_BUFFER, BCM_TX_CRC_REGEN, &(p->p_pkt)); 590 if (!p->p_pkt) { 591 test_error(unit, "Failed to allocate Tx Buffer\n"); 592 return(-1); 593 } 594 if (!p->p_sync) { 595 p->p_pkt->call_back = xmit_chain_done; 596 } 597 } 598 599 p->p_tx = (enet_hdr_t *)p->p_pkt->pkt_data[0].data; 600 601 FOREACH_P_PKT(p, i, pkt) { 602 if (p->higig_flag > 0) { 603 pkt->flags |= BCM_PKT_F_HGHDR; 604 } 605 if (p->purge_flag > 0) { 606 pkt->flags |= BCM_TX_PURGE; 607 } 608 609 if (p->p_fp) { 610 pkt->flags |= BCM_TX_FAST_PATH; 611 } else if (SOC_IS_XGS3_SWITCH(unit)) { 612 pkt->flags |= BCM_TX_ETHER; 613 } 614 615 #ifdef BCM_PETRA_SUPPORT 616 if (SOC_IS_ARAD(unit)) { 617 /** Set ssp to PTCH header and set CPU channel */ 618 tp_dune_get_ssp_and_cpu_channel(unit, pkt, p); 619 /* Fill in buffer */ 620 SOC_DPP_PKT_PTCH_HDR_SET(pkt, tp_ptch_header); 621 SOC_DPP_PKT_HDR_DMAC_SET_WITH_PTCH(pkt, p->p_dst); 622 SOC_DPP_PKT_HDR_SMAC_SET_WITH_PTCH(pkt, p->p_src); 623 if (p->p_tag) 624 { 625 SOC_DPP_PKT_HDR_TPID_SET_WITH_PTCH(pkt, (p->p_tpid)); 626 SOC_DPP_PKT_HDR_VTAG_CONTROL_SET_WITH_PTCH(pkt, VLAN_CTRL(0, 0, p->p_vid)); 627 } 628 enet_hdr = tpacket_get_enet_hdr(unit, pkt); 629 /* Fill address starts 2 * MAC + TPID + VTAG */ 630 fill_addr = BCM_PKT_DMAC(pkt) + 2 + 6 + 6; 631 if (p->p_tag) 632 { 633 fill_addr += 4; 634 } 635 } 636 else 637 #endif 638 639 #if defined (BCM_DNX_SUPPORT) 640 if (SOC_IS_DNX(unit)) { 641 /** Set ssp to PTCH header and set CPU channel */ 642 tp_dune_get_ssp_and_cpu_channel(unit, pkt, p); 643 644 /** Disable visibility resume which lower down PPS/BPS */ 645 pkt->flags |= BCM_TX_NO_VISIBILITY_RESUME; 646 647 /* Fill in buffer */ 648 TP_DNX_PKT_MH_HDR_SET(pkt, tp_mh_header); 649 TP_DNX_PKT_PTCH_HDR_SET_WITH_MH(pkt, tp_ptch_header); 650 TP_DNX_PKT_HDR_DMAC_SET_WITH_MH_PTCH(pkt, p->p_dst); 651 TP_DNX_PKT_HDR_SMAC_SET_WITH_MH_PTCH(pkt, p->p_src); 652 if (p->p_tag) 653 { 654 TP_DNX_PKT_HDR_TPID_SET_WITH_MH_PTCH(pkt, soc_htons(p->p_tpid)); 655 TP_DNX_PKT_HDR_VTAG_CONTROL_SET_WITH_MH_PTCH(pkt, soc_htons(VLAN_CTRL(0, 0, p->p_vid))); 656 } 657 enet_hdr = tpacket_get_enet_hdr(unit, pkt); 658 /* Fill address starts 2 * MAC + TPID + VTAG */ 659 fill_addr = BCM_PKT_DMAC(pkt) + DNX_MODULE_HEADER_SIZE + TP_DNX_HDR_PTCH_TYPE2_LEN + TP_DNX_MAC_ADDR_LEN + TP_DNX_MAC_ADDR_LEN; 660 if (p->p_tag) 661 { 662 fill_addr += sizeof(uint32); 663 } 664 } 665 else 666 #endif 667 { 668 enet_hdr = (enet_hdr_t *)BCM_PKT_DMAC(pkt); 669 670 /* Fill in buffer according to request */ 671 ENET_SET_MACADDR(enet_hdr->en_dhost, p->p_dst); 672 ENET_SET_MACADDR(enet_hdr->en_dhost, p->p_src); 673 if (p->p_tag) 674 { 675 enet_hdr->en_tag_tpid = soc_htons(ENET_DEFAULT_TPID); 676 enet_hdr->en_tag_ctrl = soc_htons(VLAN_CTRL(0, 0, p->p_vid)); 677 } 678 fill_addr = (uint8 *)enet_hdr + 2*sizeof(bcm_mac_t); 679 if (p->p_tag) 680 { 681 fill_addr += sizeof(uint32); 682 } 683 } 684 685 /* Store pattern */ 686 if (p->xd_pat_random) { 687 packet_random_store(fill_addr, p->len_end - 688 (fill_addr - (uint8 *)enet_hdr)); 689 } else if (XD_FILE(p) && (p->xd_usefile == TRUE)) { 690 691 fill_addr = (uint8 *)enet_hdr; 692 if (tx_load_packet_tr(unit,p->xd_file, p->xd_filelen, fill_addr) != 0) { 693 LOG_ERROR(BSL_LS_APPL_TESTS, 694 (BSL_META_U(unit, 695 "Unable to load packet from file %s\n"), 696 p->xd_file)); 697 return CMD_FAIL; 698 } 699 } else { 700 sal_memcpy( fill_addr, mypacket, p->len_end - 701 (fill_addr - (uint8 *)enet_hdr)); 702 } 703 } 704 705 return(0); 706 } 707 708 709 /* 710 * Function: tpacket_test 711 * Purpose: Test basic PCI stuff on StrataSwitch. 712 * Parameters: unit - unit #. 713 * a - pointer to arguments. 714 * pa - ignored cookie. 715 * Returns: 0 716 */ 717 718 int 719 tpacket_tx_test(int unit, args_t *a, void *pa) 720 { 721 p_t *p = (p_t *)pa; 722 int i, len, rv = BCM_E_NONE; 723 sal_usecs_t time_start, time_end; 724 enet_hdr_t *enet_hdr; 725 bcm_pkt_t *pkt; 726 uint32 elapsed_us; 727 uint32 bps; /* bytes/sec */ 728 int ql; 729 uint32 pps; /* Packets per second */ 730 uint32 tot_pkts; 731 sal_cpu_stats_t cpu_start; 732 sal_cpu_stats_t cpu_end; 733 int idle, user, kernel; 734 int idle_diff, user_diff, kernel_diff, total_diff; 735 736 COMPILER_REFERENCE(a); 737 738 tot_pkts = p->chains * p->ppc; 739 740 741 cli_out("\n" 742 " Packet | Time | Rate | Average | CPU %% \n" 743 " Size | (Sec) | p/s | MB/s | Queue | Idle /user /kern \n" 744 " --------+--------+--------+---------+---------+-------------------\n"); 745 746 for (len = p->len_start; len <= p->len_end; len += p->p_l_inc) { 747 FOREACH_P_PKT(p, i, pkt) { 748 pkt->pkt_data[0].len = len; 749 enet_hdr = tpacket_get_enet_hdr(unit, pkt); 750 if (!((XD_FILE(p) && (p->xd_usefile == TRUE)))) 751 { 752 if (p->p_tag) { 753 enet_hdr->en_tag_len = soc_htons(len); 754 } else { 755 enet_hdr->en_untagged_len = soc_htons(len); 756 } 757 } 758 } 759 p->p_cnt_accum = 0; 760 p->chains_done = 0; 761 762 /* *** Start Timer *** */ 763 764 time_start = sal_time_usecs(); 765 sal_cpu_stats_get(&cpu_start); 766 /* *** GO *** */ 767 768 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 769 if (SOC_KNET_MODE(unit) && p->p_use_socket) { 770 tot_pkts = 0; 771 for (i = 0; i < 100000; i++) { 772 if (p->p_sync) { 773 rv = send(p->p_sock, p->p_pkt->_pkt_data.data, len, 0); 774 } else { 775 rv = send(p->p_sock, p->p_pkt->_pkt_data.data, len, MSG_DONTWAIT); 776 if (rv <= 0) { 777 i--; 778 sal_usleep(1000); 779 } 780 } 781 if (rv > 0) { 782 tot_pkts++; 783 } 784 } 785 786 } else { 787 #endif 788 for (i = 0; i < p->chains; i++) { 789 if (!((p->ppc == 1) && p->p_sync)) { 790 if (sal_sem_take(p->p_sem_active, 10 * 1000000) < 0) { 791 sal_sem_give(p->p_sem_active); 792 test_error(unit, "Transmission appears stalled, semaphore release\n"); 793 return(-1); 794 } 795 } 796 p->p_cnt_accum += i - p->chains_done; 797 switch(p->p_opt) { 798 case P_O_PORT: 799 if (p->ppc == 1) { /* Packets per chain */ 800 rv = bcm_tx(unit, p->p_pkt, p); 801 } else if (p->p_array) { 802 rv = bcm_tx_array(unit, p->p_pkt_array, p->ppc, 803 xmit_chain_done, p); 804 } else { /* Linked list, multiple packets per chain */ 805 rv = bcm_tx_list(unit, p->p_pkt, xmit_chain_done, p); 806 } 807 if (rv < 0) { 808 test_error(unit, "packet send failed: %s\n", 809 bcm_errmsg(rv)); 810 } 811 break; 812 case P_O_DPP_PORT: 813 cli_out("send dpp packet start\n"); 814 rv = bcm_tx(unit, p->p_pkt, p); 815 if (rv < 0) { 816 test_error(unit, "packet send failed: %s\n", bcm_errmsg(rv)); 817 } 818 break; 819 #if defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) 820 case P_O_UC_HIT: 821 if (p->ppc == 1) { /* Packets per chain */ 822 rv = bcm_tx(unit, p->p_pkt, p); 823 } else if (p->p_array) { 824 rv = bcm_tx_array(unit, p->p_pkt_array, p->ppc, 825 xmit_chain_done, p); 826 } else { /* Linked list, multiple packets per chain */ 827 rv = bcm_tx_list(unit, p->p_pkt, xmit_chain_done, p); 828 } 829 if (rv < 0) { 830 test_error(unit, "packet send failed: %s\n", 831 bcm_errmsg(rv)); 832 } 833 break; 834 #endif 835 default: 836 /* This is already caught elsewhere */ 837 test_error(unit, "Only PortBitMap option supported " 838 "for bcm_tx\n"); 839 break; 840 } 841 if (rv < 0) { 842 /* If packet send failed, wait till the previous 843 * packet transmit is done, before exiting the test. 844 */ 845 if (sal_sem_take(p->p_sem_done, 10 * 1000000) < 0) { 846 sal_sem_give(p->p_sem_done); 847 return(-1); 848 } 849 return(-1); 850 } 851 } 852 if (!((p->ppc == 1) && p->p_sync)) { 853 if (0 > sal_sem_take(p->p_sem_done, 10 * 1000000)) { 854 test_error(unit, "Timeout waiting for completion\n"); 855 return(-1); 856 } 857 } 858 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 859 } 860 #endif 861 sal_cpu_stats_get(&cpu_end); 862 time_end = sal_time_usecs(); 863 864 COMPILER_64_SUB_64(cpu_end.total, cpu_start.total); 865 total_diff = (int)(u64_L(cpu_end.total)); 866 COMPILER_64_SUB_64(cpu_end.idle, cpu_start.idle); 867 idle_diff = (int)(u64_L(cpu_end.idle)); 868 COMPILER_64_SUB_64(cpu_end.user, cpu_start.user); 869 user_diff = (int)(u64_L(cpu_end.user)); 870 COMPILER_64_SUB_64(cpu_end.kernel, cpu_start.kernel); 871 kernel_diff = (int)(u64_L(cpu_end.kernel)); 872 873 if (total_diff != 0) { 874 idle = idle_diff * 10000UL / total_diff; 875 user = user_diff * 10000UL / total_diff; 876 kernel = kernel_diff * 10000UL / total_diff; 877 } else { 878 idle = 0; 879 user = 0; 880 kernel = 0; 881 } 882 883 if (time_end == time_start) { 884 cli_out(" %5d | ****** | ***** | ****** | ***\n", len); 885 } else { 886 elapsed_us = SAL_USECS_SUB(time_end, time_start); 887 /* Round off error limitting */ 888 if (tot_pkts > 2000) { 889 pps = tot_pkts *1000 / (elapsed_us / 1000); 890 } else { 891 pps = tot_pkts * 1000000 / elapsed_us; 892 } 893 894 bps = pps * len; 895 ql = (p->p_cnt_accum * 1000) / p->chains; 896 897 cli_out(" %5d | %2d.%03d | %6d | %3d.%03d | %3d.%03d | %2u.%02u/%2u.%02u/%2u.%02u \n", 898 len, 899 elapsed_us / 1000000, (elapsed_us % 1000000) / 1000, 900 pps, 901 bps / 1000000,(bps % 1000000) / 1000, 902 ql / 1000, ql % 1000, 903 idle / 100, idle % 100, 904 user / 100, user % 100, 905 kernel / 100, kernel % 100); 906 907 /* Sleep a bit to let current set of packets be handled */ 908 sal_usleep(500000); 909 } 910 } 911 return(0); 912 } 913 914 /*ARGSUSED*/ 915 int 916 tpacket_tx_done(int unit, void *pa) 917 /* 918 * Function: pci_test_done 919 * Purpose: Restore all values to CMIC from soc structure. 920 * Parameters: u - unit # 921 * pa - cookie (Ignored) 922 * Returns: 0 - OK 923 * -1 - failed 924 */ 925 { 926 p_t *p = p_control[unit]; 927 #if defined (BCM_ESW_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) 928 int rv; 929 #endif /* BCM_ESW_SUPPORT */ 930 bcm_pkt_t *pkt; 931 bcm_pkt_t *next_pkt; 932 933 if (p == NULL) { 934 return 0; 935 } 936 937 #if defined (BCM_ESW_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) 938 if (SOC_IS_ARAD (unit) || SOC_IS_DNX(unit)) { 939 if (0 > (rv = soc_dma_abort_channel_total(unit,0))) { 940 cli_out("Warning: soc_dma_abort(%d) failed: %s\n", 941 unit, soc_errmsg(rv)); 942 } 943 } else { 944 #if !defined(INCLUDE_KNET) 945 if (0 > (rv = soc_dma_abort(unit))) { 946 cli_out("Warning: soc_dma_abort(%d) failed: %s\n", 947 unit, soc_errmsg(rv)); 948 } 949 #endif 950 } 951 #endif /* BCM_ESW_SUPPORT */ 952 953 if (p->chains > 1) { 954 if (p->p_array) { 955 bcm_pkt_blk_free(unit, p->p_pkt_array, p->ppc); 956 } else { 957 pkt = p->p_pkt; 958 while (pkt) { 959 next_pkt = pkt->next; 960 bcm_pkt_free(unit, pkt); 961 pkt = next_pkt; 962 } 963 } 964 } else { 965 if (p->p_pkt != NULL) { 966 bcm_pkt_free(unit, p->p_pkt); 967 } 968 } 969 970 p->p_pkt_array = NULL; 971 p->p_pkt = NULL; 972 p->p_tx = NULL; 973 974 if (p->p_sem_active != NULL) { 975 sal_sem_destroy(p->p_sem_active); 976 p->p_sem_active = NULL; 977 } 978 if (p->p_sem_done != NULL) { 979 sal_sem_destroy(p->p_sem_done); 980 p->p_sem_done = NULL; 981 } 982 983 /* 984 * Don't free the p_control entry, 985 * keep it around to save argument state 986 */ 987 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 988 if (SOC_KNET_MODE(unit)) { 989 tx_knetif_clean(unit, p); 990 } 991 #endif 992 return 0; 993 } 994 995 int 996 tpacket_tx_init(int unit, args_t *a, void **pa) 997 /* 998 * Function: packet_test_init 999 * Purpose: Save all the current PCI Config registers to write 1000 * on completion. 1001 * Parameters: u - unit # 1002 * a - pointer to args 1003 * pa - Pointer to cookie 1004 * Returns: 0 - success, -1 - failed. 1005 */ 1006 { 1007 char *xfile; 1008 static char *opt_list[] = { 1009 "UCHit", "UCMiss", "MCHit", "MCMiss", "Bcast", "PortBitMap", "DPPconfig" 1010 }; 1011 p_t *p; 1012 parse_table_t pt; 1013 bcm_mcast_addr_t mc; 1014 bcm_l2_addr_t l2; 1015 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 1016 bcm_port_config_t port_config; 1017 uint32 port_ndx; 1018 int has_cpu_port = 0; 1019 #endif 1020 int rv; 1021 1022 p = p_control[unit]; 1023 if (p == NULL) { 1024 p = sal_alloc(sizeof(p_t), "tpacket"); 1025 if (p == NULL) { 1026 test_error(unit, "ERROR: cannot allocate memory\n"); 1027 return -1; 1028 } 1029 sal_memset(p, 0, sizeof(p_t)); 1030 p_control[unit] = p; 1031 } 1032 1033 if (!p->p_init) { /* Init defaults first time */ 1034 p->len_start = 64; 1035 p->len_end = 64; 1036 p->p_l_inc = 64; 1037 p->p_init = TRUE; 1038 p->chains = 1000; 1039 p->ppc = 1; 1040 #if defined (BCM_PETRA_SUPPORT) 1041 if (SOC_IS_ARAD(unit)) 1042 { 1043 p->p_vid = 0xfff; 1044 } 1045 else 1046 #endif 1047 #if defined (BCM_DNX_SUPPORT) 1048 if (SOC_IS_DNX(unit)) 1049 { 1050 p->p_vid = 0xfff; 1051 } 1052 else 1053 #endif 1054 { 1055 p->p_vid = 1; 1056 } 1057 p->xd_pat = 0x12345678; 1058 p->xd_pat_inc = 1; 1059 p->xd_pat_random = 0; 1060 p->purge_flag = FALSE; 1061 p->higig_flag = TRUE; 1062 p->ch_number=0; 1063 p->test_usage[0] = ' '; 1064 p->test_usage[1] = '\0'; 1065 p->p_array = 1; 1066 p->p_ops = 1; 1067 p->p_tag = 1; 1068 p->p_opt = P_O_PORT; 1069 p->p_tpid = ENET_DEFAULT_TPID; 1070 1071 SOC_PBMP_CLEAR(p->p_pbm); 1072 SOC_PBMP_CLEAR(p->p_upbm); 1073 SOC_PBMP_OR(p->p_pbm, PBMP_PORT_ALL(unit)); 1074 1075 p->p_sync = 1; 1076 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 1077 if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit)) 1078 { 1079 if (0 > (rv = bcm_port_config_get(unit, &port_config))) 1080 { 1081 test_error(unit, "bcm_port_config_get failed: %s\n", bcm_errmsg(rv)); 1082 return(-1); 1083 } 1084 BCM_PBMP_ITER(port_config.cpu, port_ndx) 1085 { 1086 if (port_ndx) 1087 { 1088 p->p_ptch_source_port = port_ndx; 1089 has_cpu_port =1; 1090 break; 1091 } 1092 } 1093 if (!has_cpu_port) 1094 { 1095 test_error(unit, "Failed to find a CPU port\n"); 1096 } 1097 } 1098 #endif 1099 } 1100 1101 parse_table_init(unit, &pt); 1102 1103 parse_table_add(&pt, "?", PQ_DFL|PQ_STRING, 0, &p->test_usage, 0); 1104 parse_table_add(&pt, "FastPath", PQ_DFL|PQ_BOOL, 0, &p->p_fp, 0); 1105 parse_table_add(&pt, "DestMac", PQ_DFL|PQ_MULTI, 0, &p->p_opt, opt_list); 1106 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP, 0, &p->p_pbm, 0); 1107 parse_table_add(&pt, "UntagPortBitMap", PQ_DFL|PQ_PBMP, 0, &p->p_upbm, 0); 1108 1109 parse_table_add(&pt, "Tagged", PQ_DFL|PQ_BOOL, 0, &p->p_tag, 0); 1110 parse_table_add(&pt, "VlanId", PQ_DFL|PQ_INT, 0, &p->p_vid, 0); 1111 parse_table_add(&pt, "TpId", PQ_DFL|PQ_INT, 0, &p->p_tpid, 0); 1112 parse_table_add(&pt, "LengthStart", PQ_DFL|PQ_INT, 0, &p->len_start, 0); 1113 parse_table_add(&pt, "LengthEnd", PQ_DFL|PQ_INT, 0, &p->len_end, 0); 1114 parse_table_add(&pt, "LengthInc", PQ_DFL|PQ_INT, 0, &p->p_l_inc, 0); 1115 parse_table_add(&pt, "PktsPerChain", PQ_DFL|PQ_INT, 0, &p->ppc, 0); 1116 parse_table_add(&pt, "Chains", PQ_DFL|PQ_INT, 0, &p->chains, 0); 1117 parse_table_add(&pt, "Array", PQ_DFL|PQ_BOOL, 0, &p->p_array, 0); 1118 parse_table_add(&pt, "Operations", PQ_DFL|PQ_INT, 0, &p->p_ops, 0); 1119 1120 parse_table_add(&pt, "HIGig", PQ_DFL|PQ_BOOL ,0, &p->higig_flag, 0); 1121 parse_table_add(&pt, "PURge", PQ_DFL|PQ_BOOL ,0, &p->purge_flag, 0); 1122 parse_table_add(&pt, "CHNUMber", PQ_DFL|PQ_INT ,0, &p->ch_number, 0); 1123 parse_table_add(&pt, "MacDest", PQ_DFL|PQ_MAC, 0,&p->p_dst, NULL); 1124 parse_table_add(&pt, "MacSrc", PQ_DFL|PQ_MAC, 0,&p->p_src, NULL); 1125 parse_table_add(&pt, "Pattern", PQ_DFL|PQ_HEX, 0, &p->xd_pat, NULL); 1126 parse_table_add(&pt, "PatternInc", PQ_DFL|PQ_INT, 0, &p->xd_pat_inc, NULL); 1127 parse_table_add(&pt, "PatternRandom", PQ_DFL|PQ_BOOL, 0, &p->xd_pat_random, NULL); 1128 parse_table_add(&pt, "Filename", PQ_DFL|PQ_STRING,0, &p->xd_file, NULL); 1129 parse_table_add(&pt, "FileLen", PQ_DFL|PQ_INT ,0, &p->xd_filelen, NULL); 1130 parse_table_add(&pt, "UseFile", PQ_DFL|PQ_BOOL ,0, &p->xd_usefile, NULL); 1131 1132 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 1133 parse_table_add(&pt, "Socket", PQ_DFL|PQ_BOOL ,0, &p->p_use_socket, 0); 1134 #endif 1135 parse_table_add(&pt, "Sync", PQ_DFL|PQ_BOOL ,0, &p->p_sync, 0); 1136 1137 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 1138 parse_table_add(&pt, "PtchSRCport", PQ_DFL|PQ_BOOL ,0, &p->p_ptch_source_port, 0); 1139 #endif 1140 if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) { 1141 test_error(unit, "%s: Invalid option: %s\n", 1142 ARG_CMD(a), ARG_CUR(a) ? ARG_CUR(a) : "*"); 1143 parse_arg_eq_done(&pt); 1144 1145 cli_out("%s\n",tr40_test_usage); 1146 1147 return(-1); 1148 } 1149 1150 if (p->xd_file) { 1151 xfile = sal_strdup(p->xd_file); 1152 } else { 1153 xfile = NULL; 1154 } 1155 parse_arg_eq_done(&pt); 1156 1157 if (p->test_usage[0] == '?') { 1158 cli_out("%s\n",tr40_test_usage); 1159 } 1160 p->xd_file = xfile; 1161 1162 if (p->p_ops > 1000) { 1163 test_error(unit, "Operations must be 1 <= # <= 1000\n"); 1164 return(-1); 1165 } 1166 1167 if ((p->p_opt != P_O_PORT) && (!(SOC_IS_ARAD(unit) || SOC_IS_DNX(unit)))) { 1168 test_error(unit, "Only PortBitMap option supported for bcm_tx\n"); 1169 return -1; 1170 } 1171 1172 if (p->len_end > PACKET_MAX_BUFFER) { 1173 test_error(unit, "Max supported pkt size is %d\n", PACKET_MAX_BUFFER); 1174 p->len_end = PACKET_MAX_BUFFER; 1175 return -1; 1176 } 1177 1178 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 1179 if (!SOC_KNET_MODE(unit) && p->p_use_socket) { 1180 cli_out("KNET not online, please insert the kernel module firstly.\n"); 1181 return -1; 1182 } 1183 #endif 1184 1185 /* Insert ARL/MARL entry */ 1186 1187 switch(p->p_opt) { 1188 case P_O_UC_HIT: 1189 if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit)) 1190 { 1191 p->p_vid = 1; 1192 } 1193 bcm_l2_addr_t_init(&l2, tp_mac_uc, p->p_vid); 1194 l2.flags |= BCM_L2_STATIC; 1195 if (0 > (rv = bcm_l2_addr_add(unit, &l2))) { 1196 test_error(unit, "bcm_l2_addr_add failed: %s\n", bcm_errmsg(rv)); 1197 return(-1); 1198 } 1199 ENET_SET_MACADDR(p->p_dst, tp_mac_uc); 1200 break; 1201 case P_O_UC_MISS: 1202 if (0 > (rv = bcm_l2_addr_delete(unit, tp_mac_uc, p->p_vid))) { 1203 test_error(unit, "bcm_l2_addr_delete failed: %s\n", bcm_errmsg(rv)); 1204 return(-1); 1205 } 1206 ENET_SET_MACADDR(p->p_dst, tp_mac_uc); 1207 break; 1208 case P_O_MC_HIT: 1209 bcm_mcast_addr_t_init(&mc, tp_mac_mc, p->p_vid); 1210 if (0 > (rv = bcm_mcast_addr_add(unit, &mc))) { 1211 test_error(unit, "bcm_mcast_addr_add failed: %s\n", bcm_errmsg(rv)); 1212 return(-1); 1213 } 1214 ENET_SET_MACADDR(p->p_dst, tp_mac_mc); 1215 break; 1216 case P_O_MC_MISS: 1217 if (0 > (rv = bcm_mcast_addr_remove(unit, tp_mac_mc, p->p_vid))) { 1218 if (rv != BCM_E_NOT_FOUND) { 1219 test_error(unit, "bcm_mcast_addr_remove failed: %s\n", bcm_errmsg(rv)); 1220 return(-1); 1221 } 1222 } 1223 ENET_SET_MACADDR(p->p_dst, tp_mac_mc); 1224 break; 1225 1226 case P_O_BC: 1227 ENET_SET_MACADDR(p->p_dst, tp_mac_bc); 1228 break; 1229 case P_O_PORT: 1230 if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit)) { 1231 1232 if(!ENET_CMP_MACADDR(p->p_dst, tp_mac_empty)) { 1233 ENET_SET_MACADDR(p->p_dst, tp_mac_dpp_dst); 1234 } 1235 1236 if(!ENET_CMP_MACADDR(p->p_src, tp_mac_empty)) { 1237 ENET_SET_MACADDR(p->p_src, tp_mac_dpp_src); 1238 } 1239 } else 1240 { 1241 ENET_SET_MACADDR(p->p_dst, tp_mac_bc); 1242 } 1243 1244 break; 1245 1246 case P_O_DPP_PORT: 1247 1248 ENET_SET_MACADDR(p->p_dst, tp_mac_dpp_dst); 1249 ENET_SET_MACADDR(p->p_src, tp_mac_dpp_src); 1250 break; 1251 default: 1252 return(-1); 1253 } 1254 1255 if (tpacket_setup(unit, p) < 0) { 1256 (void)tpacket_tx_done(unit, p); 1257 return(-1); 1258 } 1259 1260 *pa = (void *)p; 1261 1262 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 1263 if (SOC_KNET_MODE(unit)) { 1264 tx_knetif_setup(unit, p); 1265 } 1266 #endif 1267 1268 return(0); 1269 } 1270 1271 STATIC int8 1272 tx_load_packet_tr(int unit, char *fname, int length, uint8 *packet_in) 1273 { 1274 1275 #if (defined(LINUX) && (!defined(__KERNEL__)) && (!defined(NO_SAL_APPL))) 1276 FILE * pFile; 1277 long size; 1278 uint8 *ptr; 1279 int i; 1280 int8 c; 1281 1282 ptr = packet_in; 1283 pFile = sal_fopen(fname,"rb"); 1284 if (pFile==NULL) return -1; 1285 else 1286 { 1287 sal_fseek (pFile, 0, SEEK_END); 1288 size=sal_ftell (pFile); 1289 if (sal_fseek (pFile, 0, SEEK_SET) != 0){ 1290 sal_fclose (pFile); 1291 return -1; 1292 } 1293 if (size < length) { 1294 sal_fclose (pFile); 1295 return -1; 1296 } 1297 for (i = 0; i < length; i++) { 1298 c = (int8)sal_fgetc(pFile); 1299 *ptr++ = (uint8)c; 1300 } 1301 sal_fclose (pFile); 1302 } 1303 #endif /*(defined(LINUX) && (!defined(__KERNEL__)) && (!defined(NO_SAL_APPL)) */ 1304 return 0; 1305 } 1306 1307 1308 1309 1310 1311 1312 1313 1314