openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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