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

rpacket.c (69220B)


      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 receive test that uses the BCM api.
      8  *
      9  * December, 2002:  Options added to support RX APIs.
     10  *    This also adds:
     11  *        interrupt/non-interrupt handling;
     12  *        packet stealing;
     13  *        if stealing, freeing packets with DPC (always with interrupt,
     14  *               optionally with non-interrupt) or immediately;
     15  *
     16  *    When stealing packets, the system will crash if the rate is
     17  *    high enough:  Over 4K pkts/sec on Mousse, and 6K pkts/sec on BMW.
     18  *    This does not appear to be related to DPC.
     19  *
     20  *    Current max rates for RX API, no packet stealing:
     21  *       BMW (8245) on 5690, interrupt:           11.6 K pkts/sec
     22  *       BMW, non-interrupt:                      11.6 K pkts/sec
     23  *       Mousse, non-interrupt:                   10.4 K pkts/sec
     24  *
     25  *    Update on max rates for RX API:
     26  */
     27 
     28 #include <sal/types.h>
     29 #include <sal/core/time.h>
     30 #include <sal/core/stats.h>
     31 #include <sal/appl/sal.h>
     32 #include <sal/core/dpc.h>
     33 #include <shared/bsl.h>
     34 #include <soc/util.h>
     35 #include <soc/drv.h>
     36 
     37 #include <appl/diag/system.h>
     38 #include <appl/diag/parse.h>
     39 #include <appl/diag/shell.h>
     40 
     41 #include <bcm/error.h>
     42 #include <bcm/l2.h>
     43 #include <bcm/mcast.h>
     44 #include <bcm/port.h>
     45 #include <bcm/link.h>
     46 #include <bcm/field.h>
     47 #include <bcm/rx.h>
     48 #include <bcm/pkt.h>
     49 #include <bcm/stack.h>
     50 #include <bcm/vlan.h>
     51 
     52 #include <bcm_int/common/rx.h>
     53 #include <bcm_int/common/tx.h>
     54 #if defined (BCM_PETRA_SUPPORT)
     55 #include <soc/dpp/drv.h>
     56 #endif
     57 #if defined (BCM_DNX_SUPPORT)
     58 #include <src/appl/reference/dnx/appl_ref_rx_init.h>
     59 #endif
     60 
     61 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
     62 #include <bcm/knet.h>
     63 #include <errno.h>
     64 #include <stdio.h>
     65 #include <unistd.h>
     66 #include <arpa/inet.h>
     67 #include <sys/socket.h>
     68 #include <linux/if_ether.h>
     69 #include <linux/if_packet.h>
     70 #include <linux/if.h>
     71 #include <sys/ioctl.h>
     72 #include <sys/poll.h>
     73 #include <sys/mman.h>
     74     
     75 #include <sched.h>
     76 #include <sal/core/thread.h>
     77 #endif
     78 
     79 
     80 #include "testlist.h"
     81 
     82 #if defined(BCM_FIELD_SUPPORT) || defined(BCM_FE2000_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT)
     83 
     84 typedef struct p_s {
     85     int                         p_init; /* TRUE --> initialized */
     86 
     87     /* parameters changed or watched by other threads -- must be volatile */
     88     volatile uint32             p_count_packets; /* Finished test - just drain */
     89     volatile uint32             p_received;
     90     volatile uint32             p_drained;
     91     volatile uint32             p_time_us;
     92     volatile uint32             p_error_num;
     93 
     94     /* internal parameters */
     95     int                         p_num_test_ports;
     96     int                         p_use_fp_action;
     97     int                         p_port[2]; /* Active port */
     98     int                         p_time; /* Duration (seconds) */
     99     bcm_port_info_t             p_port_info[2]; /* saved port config */
    100     int                         p_pkts_per_sec;
    101     int                         p_hw_rate;  /* use hw rate limiting */
    102     int                         p_max_q_len;
    103     int                         p_per_cos; /* Run tests with per-cos settings */
    104     int                         p_burst;
    105     uint32                      reg_flags;  /* Flags used for register */
    106     int                         p_intr_cb;
    107     int                         p_dump_rx;
    108 #if defined(BCM_FIELD_SUPPORT)
    109     bcm_field_entry_t           p_field_entry[2];
    110 #endif /* BCM_FIELD_SUPPORT */
    111     int                         p_l_start; /* Length start */
    112     int                         p_l_end; /* Length end */
    113     int                         p_l_inc; /* Length increment */
    114     int                         p_free_buffer;
    115     bcm_pkt_t                   *p_pkt; /* Tx - Packet buffer */
    116     bcm_rx_cfg_t                p_rx_cfg;
    117     int                         rx_mode;
    118     int                         p_txrx_unit;
    119 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
    120     int                         p_use_socket;
    121     int                         p_sock;
    122     int                         p_netid;
    123     int                         p_filterid;
    124     sal_thread_t                p_threadid;
    125     int                         p_ringbuf_size;
    126     char *                      p_ringbuf;
    127     int                         p_use_socket_send;
    128 #endif
    129     int                         hdr_chk; /* Flag to check EP_TO_CPU header on CMICx */
    130     int                         diff_len; /* Acceptable difference between s_len and r_len */
    131     int                         diff_len_chk; /* Flag to check difference between s_len and r_len */
    132 } p_t;
    133 
    134 static sal_mac_addr_t rp_mac_dest = {0x00, 0x11, 0x22, 0x33, 0x44, 0x99};
    135 static sal_mac_addr_t rp_mac_src  = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66};
    136 
    137 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT)
    138 int is_force_local = 0;
    139 int is_force_fabric = 0;
    140 static uint8 rp_ptch_header[2]  = {0xd0, 0x00};
    141 static uint8 mypacket[] = {
    142 
    143 
    144 /*
    145                           0x0,0x0,0x0,0x0,       0x0,0x1,0x0,0x0,
    146                           0x0,0x0,0x0,0xe2,      0x81,0x00,0x00,0x00,
    147                           
    148                           0x90,0x00,*/0x1,0x2, 
    149 
    150 
    151 
    152 
    153 /*                          0x0,0x0,0x0,0x0,       0x0,0x1,0x0,0x0,
    154                           0x0,0x0,0x0,0xe2,      0x90,0x00,0x1,0x2,
    155                           
    156                           0x03,0x4,0x5,0x6, */     0x7,0x8,0x9,0xa,
    157                           0xb,0xc,0xd,0xe,       0xf,0x10,0x11,0x12,
    158                           
    159                           0x13,0x14,0x15,0x16,   0x17,0x18,0x19,0x1a,
    160                           0x1b,0x1c,0x1d,0x1e,   0x1f,0x20,0x21,0x22,
    161                           
    162                           0x23,0x24,0x25,0x26,   0x27,0x28,0x29,0x2a,
    163                           0x2b,0x2c,0x2d,0x2e,   0x2f,0x30,0x31,0x32,
    164                           
    165                           0x33,0x34,0x35,0x36,   0x37,0x38,0x39,0x3a,
    166                           0x3b,0x3c,0x3d,0x3e,   0x3f,0x40,0x41,0x42,
    167 
    168                           0x43,0x44,0x45,0x46,   0x47,0x48,0x49,0x4a,
    169                           0x4b,0x4c,0x4d,0x4e,   0x4f,0x50,0x51,0x52,
    170 
    171 
    172                           0x53,0x54,0x55,0x56,   0x57,0x58,0x59,0x5a,
    173                           0x5b,0x5c,0x5d,0x5e,   0x5f,0x60,0x61,0x62,
    174 
    175                           0x63,0x64,0x65,0x66,   0x67,0x68,0x69,0x6a,
    176                           0x6b,0x6c,0x6d,0x6e,   0x6f,0x70,0x71,0x72,
    177 
    178                           0x73,0x74,0x75,0x76,   0x77,0x78,0x79,0x7a,
    179                           0x7b,0x7c,0x7d,0x7e,   0x7f,0x80,0x81,0x82 };
    180 #endif
    181 
    182 #ifdef BCM_DNX_SUPPORT
    183 static uint8 rp_mh_header[16]  = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    184 #endif
    185 
    186 
    187 static p_t *p_control[SOC_MAX_NUM_DEVICES];
    188 
    189 #define RP_RECEIVER_PRIO                255    /* Priority of rx handler */
    190 #define RP_MAX_PKT_LENGTH               2048
    191 #define RP_RX_CHANNEL                   1      /* DMA channel */
    192 
    193 
    194 #define RP_CHK(rv, f)                      \
    195    if (BCM_FAILURE((rv))) {                \
    196        cli_out("call to %s line %d failed:%d %s\n", #f, __LINE__,\
    197                (rv), bcm_errmsg((rv))); \
    198     }
    199 
    200 
    201 #define RP_MAX_PPC SOC_DV_PKTS_MAX
    202 
    203 #ifndef DNX_MODULE_HEADER_SIZE
    204 /** Define length of Module Header */
    205 #if defined(BCM_DNX_SUPPORT) && !defined(ADAPTER_SERVER_MODE)
    206 /** Size of module header on DNX devices, it should be written at the start of the packet */
    207 #define DNX_MODULE_HEADER_SIZE         16
    208 #else
    209 /** No Module Header on ADAPTER and non DNX*/
    210 #define DNX_MODULE_HEADER_SIZE         0
    211 #endif
    212 #endif
    213 
    214 #ifdef BCM_DNX_SUPPORT
    215 /** Define length PTCH-2 */
    216 #define RP_DNX_HDR_PTCH_TYPE2_LEN       2
    217 #define RP_DNX_MAC_ADDR_LEN             6
    218 
    219 /* Helper macro for appending Module Header to ethernet packets */
    220 #define RP_DNX_PKT_MH_HDR_SET(pkt, mh)  \
    221     sal_memcpy((pkt)->_pkt_data.data, (mh), DNX_MODULE_HEADER_SIZE)
    222 
    223 /* Helper macro for appending PTCH2 header to ethernet packets with Module Header */
    224 #define RP_DNX_PKT_PTCH_HDR_SET_WITH_MH(pkt, ptch)  \
    225     sal_memcpy((pkt)->_pkt_data.data + DNX_MODULE_HEADER_SIZE, (ptch), RP_DNX_HDR_PTCH_TYPE2_LEN)
    226 
    227 /* Helper macro for setting DMAC to ethernet packets with Module Header and PTCH2 header */
    228 #define RP_DNX_PKT_HDR_DMAC_SET_WITH_MH_PTCH(pkt, dmac)  \
    229     sal_memcpy((pkt)->_pkt_data.data + DNX_MODULE_HEADER_SIZE + RP_DNX_HDR_PTCH_TYPE2_LEN, (dmac), RP_DNX_MAC_ADDR_LEN)
    230 
    231 /* Helper macro for setting SMAC to ethernet packets with Module Header and PTCH2 header */
    232 #define RP_DNX_PKT_HDR_SMAC_SET_WITH_MH_PTCH(pkt, smac)  \
    233     sal_memcpy((pkt)->_pkt_data.data + DNX_MODULE_HEADER_SIZE + RP_DNX_HDR_PTCH_TYPE2_LEN + 6, (smac), RP_DNX_MAC_ADDR_LEN)
    234 
    235 /* Helper macro for setting uint16 to specified position of packet val in network byte order */
    236 #define RP_DNX_HTONS_CVT_SET(pkt, val, posn)  \
    237     do { \
    238          uint16 _tmp; \
    239          _tmp = soc_htons(val); \
    240          sal_memcpy((pkt)->_pkt_data.data + (posn), &_tmp, sizeof(uint16)); \
    241     } while (0)
    242 
    243 /* Helper macro for setting TPID to ethernet packets with Module Header and PTCH header */
    244 #define RP_DNX_PKT_HDR_TPID_SET_WITH_MH_PTCH(pkt, tpid)  \
    245     RP_DNX_HTONS_CVT_SET(pkt, tpid, DNX_MODULE_HEADER_SIZE + RP_DNX_HDR_PTCH_TYPE2_LEN + RP_DNX_MAC_ADDR_LEN + RP_DNX_MAC_ADDR_LEN)
    246 
    247 /* Helper macro for setting vlan tag to ethernet packets with Module Header and PTCH header */
    248 #define RP_DNX_PKT_HDR_VTAG_CONTROL_SET_WITH_MH_PTCH(pkt, vtag)  \
    249     RP_DNX_HTONS_CVT_SET(pkt, vtag, DNX_MODULE_HEADER_SIZE + RP_DNX_HDR_PTCH_TYPE2_LEN + RP_DNX_MAC_ADDR_LEN + RP_DNX_MAC_ADDR_LEN + sizeof(uint16))
    250 
    251 /* Helper macro for single buffer Ethernet packet with PTCH header(not HiGig). */
    252 #define RP_DNX_PKT_HDR_TAGGED_LEN_SET_WITH_MH_PTCH(pkt, len)  \
    253     RP_DNX_HTONS_CVT_SET(pkt, len, DNX_MODULE_HEADER_SIZE + RP_DNX_HDR_PTCH_TYPE2_LEN + RP_DNX_MAC_ADDR_LEN + RP_DNX_MAC_ADDR_LEN + sizeof(uint32))
    254 #endif
    255 
    256 STATIC void 
    257 debug_dump(int len, uint8 *data)
    258 {
    259     int i;
    260     char tbuf[128];
    261 
    262     sal_memset(tbuf, 0, 128);
    263     for (i = 0; i< len; i++) {
    264            sal_sprintf(tbuf+(i % 16)*3, "%02x ", data[i]);
    265            if (((i+1) % 16) == 0) {
    266                cli_out("%s\n", tbuf);
    267                sal_memset(tbuf, 0, 128);
    268            }
    269     }
    270     cli_out("%s\n", tbuf);
    271 }
    272 
    273 STATIC void
    274 packet_measure(p_t *p, int s_len, int r_len, uint8 *buf, int len_adj)
    275 {
    276     static sal_usecs_t  time_start = 0, hdr_len = 0;
    277     sal_usecs_t  time_end = 0;
    278 
    279     /* keep accumulating stats */
    280     p->p_received++;
    281     /* one packet has been received; track stats */
    282     if (p->p_received == 1) {
    283         time_start = sal_time_usecs();
    284     } else {
    285         time_end = sal_time_usecs();
    286         /* again overkill to calculate on each packet, but
    287            the main test is going to make off with this value
    288            at any time, so we have to keep it up to date */
    289         p->p_time_us = (int)(time_end - time_start);
    290     }
    291 
    292     if (!p->hdr_chk) {
    293 #ifdef BCM_CMICX_SUPPORT
    294         if (soc_feature(p->p_txrx_unit, soc_feature_cmicx)) {
    295             hdr_len = soc_cmicx_pktdma_header_size_get(p->p_txrx_unit);
    296         }
    297 #endif
    298         p->hdr_chk = 1;
    299     }
    300 
    301     if (len_adj) {
    302         r_len -= hdr_len;
    303     }
    304 
    305     if (p->diff_len_chk && (abs(r_len - s_len) > p->diff_len)) {
    306         /* packet error */
    307         p->p_error_num++;
    308         if (p->p_error_num == 1) {
    309             cli_out("S:%d R:%d\n", s_len, r_len);
    310             debug_dump(96, buf);
    311         }
    312     }
    313 }
    314 
    315 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
    316 
    317 
    318 #define RXRING_FRAME_SIZE  (2048)
    319 #define MAX_RXRING_FRAMES  (1024)
    320 
    321 static int idx = 0;
    322 
    323 
    324 STATIC void
    325 _set_thread_priority(int prio)
    326 {
    327     struct sched_param param;
    328     param.sched_priority = prio;
    329     if (sched_setscheduler(0, SCHED_RR, &param)) {       
    330         cli_out("priority set: \n");
    331     }
    332 }
    333 
    334 STATIC int 
    335 knet_stats_get(long unsigned int *ic, long unsigned int *tc)
    336 {
    337     FILE* f;
    338     unsigned int tmp, int_cnt, pkt_cnt0, pkt_cnt1, pkt_cnt2;
    339 
    340     if ((f=fopen("/proc/bcm/knet/stats", "rw" )) == NULL) {
    341         *tc = 0;
    342         return -1;
    343     }
    344     (void)fscanf(f, "Device stats (unit %d):\n"\
    345                     "  Interrupts  %10u\n"\
    346                     "  Tx packets  %10u\n"\
    347                     "  Rx0 packets %10u\n"\
    348                     "  Rx1 packets %10u\n"\
    349                     "  Rx2 packets %10u\n"\
    350                     "  Rx0 pkts/intr %8u\n"\
    351                     "  Rx1 pkts/intr %8u\n"\
    352                     "  Rx2 pkts/intr %8u\n",
    353                     (int *)&tmp, &int_cnt, &tmp,
    354                     &pkt_cnt0, &pkt_cnt1, &pkt_cnt2,
    355                     &tmp, &tmp, &tmp);
    356     * ic = int_cnt;
    357     * tc = pkt_cnt0 + pkt_cnt1 + pkt_cnt2;
    358     fclose(f);
    359     
    360     return 0;
    361     
    362 }
    363 
    364 STATIC int 
    365 knet_stats_clear(void)
    366 {
    367     FILE* f;
    368 
    369     if ((f=fopen("/proc/bcm/knet/stats", "w+" )) == NULL) {
    370         cli_out("fail to open stats for writing\n");
    371         return -1;
    372     }
    373     fwrite("clear", 5, 1, f);
    374     fclose(f);
    375     return 0;
    376     
    377 }
    378 
    379 #ifdef FIX_IDX_ORDER
    380 
    381 STATIC int 
    382 fix_idx(int idx ,volatile p_t* p, int *len) 
    383 {
    384     int max = p-> p_ringbuf_size;
    385     int i =  (idx+1) % max;
    386     
    387     while (i != idx) {
    388 #ifdef PACKET_VERSION
    389         volatile struct tpacket2_hdr *head = (volatile struct tpacket2_hdr *)
    390             (p->p_ringbuf + i * RXRING_FRAME_SIZE);
    391 #else 
    392         volatile struct tpacket_hdr *head = (volatile struct tpacket_hdr *)
    393             (p->p_ringbuf + i * RXRING_FRAME_SIZE);        
    394 #endif 
    395         if (head->tp_status & TP_STATUS_USER) {
    396             * len = head->tp_len;
    397             head->tp_len = 0;
    398             head->tp_snaplen = 0;
    399             head->tp_status = TP_STATUS_KERNEL;
    400             
    401             return i;
    402         }
    403         i=(i+1) % max;
    404     }
    405     return i;
    406 }
    407 #endif
    408 
    409 STATIC int 
    410 sock_read_one_pkt (volatile p_t* p, uint8 ** pbuf)
    411 {
    412     static char sock_buf[RXRING_FRAME_SIZE];
    413     int len = 0;
    414 
    415     if (p->p_ringbuf) {   /* ring buffer receive */                 
    416 
    417 #ifdef PACKET_VERSION
    418         volatile struct tpacket2_hdr *head = (volatile struct tpacket2_hdr *)
    419             (p->p_ringbuf + idx * RXRING_FRAME_SIZE);
    420 #else 
    421         volatile struct tpacket_hdr *head = (volatile struct tpacket_hdr *)
    422             (p->p_ringbuf + idx * RXRING_FRAME_SIZE);        
    423 #endif
    424         
    425         * pbuf = (uint8 *)head;
    426 
    427         if (head->tp_status & TP_STATUS_USER) { /* it's our packet */
    428             len = head->tp_len;
    429             /* release the ringbuf entry back to the kernel */
    430             head->tp_len = 0;
    431             head->tp_snaplen = 0;
    432             head->tp_status = TP_STATUS_KERNEL;
    433         
    434             /* next packet */
    435             idx = (idx + 1) % (p->p_ringbuf_size);
    436         } else {
    437 #ifdef FIX_IDX_ORDER
    438             int fixed_idx = fix_idx(idx, p, &len);
    439             if (fixed_idx !=  idx) {
    440                 idx = (fixed_idx+1) %(p->p_ringbuf_size);
    441                 
    442             } 
    443 #endif
    444         }
    445 
    446     } else {  /* standard socket receive */
    447         * pbuf = (uint8 *)sock_buf;
    448         len = recvfrom(p->p_sock, sock_buf, RXRING_FRAME_SIZE, MSG_DONTWAIT, NULL, NULL);  
    449         if (len < 0) {
    450             len = 0;
    451         }
    452     }
    453 
    454     return len;
    455 } /* sock_read_one_pkt*/
    456 
    457 
    458 STATIC void 
    459 socket_receive(void *arg)
    460 {
    461     p_t *p = (p_t *)arg;
    462     int          len = 0;
    463     struct       pollfd pfd;    
    464     uint8 * buf;
    465    
    466     _set_thread_priority(50);
    467        
    468     if (p->p_sock <= 0) {
    469         cli_out("bad socket %d\n", p->p_sock);
    470         return;
    471     }
    472 
    473     sal_memset(&pfd, 0, sizeof(pfd));
    474     pfd.fd = p->p_sock;
    475     pfd.events = POLLIN /*| POLLERR*/;  
    476     pfd.revents = 0;
    477 
    478     while (TRUE) {
    479         pfd.revents = 0;
    480         /* wait for data to arrive*/
    481         len = poll(&pfd, 1, -1);
    482 
    483         if (len == -1) {
    484             if (errno != EINTR) {
    485                 cli_out("poll error: errno %d\n", errno);
    486             }
    487             continue;   
    488         } else if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
    489             cli_out("poll exception; revents 0x%x\n", pfd.revents);
    490             continue;
    491         } else if ((pfd.revents & POLLIN) == 0) {
    492             cli_out("poll without data; revents %x\n", pfd.revents);
    493             continue;
    494         }
    495   
    496         /* pull packet from socket until empty*/
    497         while ((len = sock_read_one_pkt (p, &buf)) > 0) {
    498             if (p->p_count_packets) {
    499                 packet_measure(p, p->p_pkt->_pkt_data.len, len, buf, 0);
    500             } else {
    501                 p->p_drained++;
    502             }
    503         } /* while packet len > 0 */
    504 
    505     } /* while processing packets */
    506 
    507     cli_out("socket_receive thread done.\n");
    508     /* spin forever, waiting to be killed */
    509     for (;;) {
    510     }
    511 
    512 } /* socket_receive */
    513 
    514 
    515 STATIC int 
    516 bind_device(int sock, char* dev)
    517 {
    518     int rv;
    519     struct sockaddr_ll addr;    
    520     struct ifreq req;
    521     
    522     sal_memset(&req, 0, sizeof(req));
    523     sal_strncpy(req.ifr_name, dev, sizeof(req.ifr_name));
    524     if ((rv = ioctl(sock, SIOCGIFINDEX, &req)) < 0) {
    525         cli_out("ioctl error %d\n", errno);
    526         return rv;
    527     }  
    528 
    529     if ((rv = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, 
    530                         (void *)&req, sizeof(req))) < 0) {
    531         cli_out("bind_device setsockopt error %d\n", errno); 
    532         return rv;
    533     }
    534 
    535     sal_memset(&addr, 0, sizeof(addr));
    536     addr.sll_family = AF_PACKET;
    537     addr.sll_protocol = htons(0x8100);
    538     addr.sll_ifindex = req.ifr_ifindex;
    539     addr.sll_hatype = 0;
    540     addr.sll_pkttype = 0;
    541     addr.sll_halen = 0;
    542     if ((rv = bind(sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
    543         cli_out("bind error %d\n", errno);
    544         return rv;
    545     }
    546     return 0;
    547 }
    548 
    549 STATIC int
    550 set_promisc_up(int sock,  char* dev)
    551 {
    552     struct ifreq req;       
    553     sal_strncpy(req.ifr_name, dev, sizeof(req.ifr_name));
    554     
    555     if (ioctl(sock, SIOCGIFFLAGS, &req)==-1) {
    556         cli_out("ioctl error");
    557         return -1;
    558     }
    559     req.ifr_flags |= (IFF_PROMISC | IFF_UP | IFF_RUNNING);
    560     if (ioctl(sock, SIOCSIFFLAGS, &req)==-1) {
    561         cli_out("ioctl error");
    562         return -1;
    563     }
    564     return 0;
    565 }
    566 STATIC int
    567 knetif_setup(int unit, p_t *p) 
    568 {  
    569     int rv;
    570     bcm_knet_netif_t netif;
    571     bcm_knet_filter_t filter;
    572     struct tpacket_req  req;
    573     
    574     bcm_knet_netif_t_init(&netif);
    575     netif.type = BCM_KNET_NETIF_T_TX_CPU_INGRESS;
    576     sal_memcpy(netif.mac_addr, rp_mac_dest, 6);
    577     
    578     p->p_netid = 0;
    579     rv = bcm_knet_netif_create(unit, &netif);
    580     if (BCM_SUCCESS(rv)) {
    581         p->p_netid = netif.id;
    582     } else {
    583         cli_out("bcm_knet_netif_create failed: %d\n", rv);
    584         return rv;
    585     }
    586     
    587     p->p_filterid = 0;
    588     bcm_knet_filter_t_init(&filter);
    589     filter.type = BCM_KNET_FILTER_T_RX_PKT;
    590     if (p->p_use_socket) {
    591         filter.dest_type = BCM_KNET_DEST_T_NETIF;
    592         filter.dest_id = p->p_netid; 
    593     } else {
    594         filter.dest_type = BCM_KNET_DEST_T_BCM_RX_API;
    595     }
    596     rv = bcm_knet_filter_create(unit, &filter);
    597     if (BCM_SUCCESS(rv)) {
    598         p->p_filterid = filter.id;
    599     } else {
    600         cli_out("bcm_knet_filter_create:%d\n", rv);
    601         return rv;
    602     }
    603     
    604     p->p_sock = socket(AF_PACKET, SOCK_RAW, htons(0x8100));
    605 
    606     set_promisc_up(p->p_sock, "bcm0");
    607     set_promisc_up(p->p_sock, netif.name);
    608 
    609         /* set up ring buffer, if needed */
    610     if ((p->p_use_socket) && (p->p_ringbuf_size > 0)) {
    611         int buf_size = p->p_ringbuf_size * RXRING_FRAME_SIZE; 
    612 #ifdef PACKET_VERSION 
    613         int tpacket_version = TPACKET_V2;
    614         /* set tpacket hdr version. */
    615         if (-1 == setsockopt (p->p_sock, SOL_PACKET, PACKET_VERSION, 
    616             &tpacket_version, sizeof (int))) {
    617             cli_out("set tpacket version failure.\n");
    618         }
    619 #endif        
    620         idx = 0;
    621 
    622         req.tp_block_size = buf_size;
    623         req.tp_block_nr = 1;
    624         req.tp_frame_size = RXRING_FRAME_SIZE;
    625         req.tp_frame_nr = p->p_ringbuf_size;
    626         
    627         if (-1 == setsockopt(p->p_sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req))) {
    628             cli_out("setsockopt PACKET_RX_RING error\n");  
    629         }
    630         p->p_ringbuf = (char*)mmap(0, buf_size, PROT_READ|PROT_WRITE, MAP_SHARED, p->p_sock, 0);
    631         if (MAP_FAILED == p->p_ringbuf) {
    632             cli_out("mmap error\n");
    633             p->p_ringbuf = NULL;
    634             p->p_ringbuf_size = 0;
    635         } else {
    636             memset(p->p_ringbuf, 0, buf_size);
    637         }
    638     }
    639     bind_device(p->p_sock, netif.name);
    640     if (p->p_use_socket) {     
    641         p->p_threadid = sal_thread_create("sock_rx", 8192, 50, socket_receive, p);
    642     }
    643     return rv;
    644 }
    645 
    646 STATIC void
    647 knetif_clean(int unit, p_t *p) 
    648 {
    649     if (p->p_threadid != NULL) {
    650         sal_thread_destroy(p->p_threadid);
    651         p->p_threadid = NULL;
    652     }
    653     
    654     if (p->p_ringbuf != NULL) {
    655         struct tpacket_req  req;
    656         int buf_size = p->p_ringbuf_size * RXRING_FRAME_SIZE;
    657         sal_memset(&req, 0, sizeof(req));
    658         setsockopt(p->p_sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
    659         munmap(p->p_ringbuf, buf_size);
    660         p->p_ringbuf = NULL;
    661     }
    662     if (p->p_sock > 0) {
    663         struct ifreq req;
    664         bcm_knet_netif_t netif;
    665         bcm_knet_netif_get(unit, p->p_netid, &netif);
    666        
    667         sal_strncpy(req.ifr_name, netif.name, sizeof(req.ifr_name));
    668         
    669         if (ioctl(p->p_sock, SIOCGIFFLAGS, &req)==-1) {
    670             cli_out("ioctl SIOCGIFFLAGS error");
    671         }
    672         req.ifr_flags &= (~(IFF_UP | IFF_RUNNING));
    673         if (ioctl(p->p_sock, SIOCSIFFLAGS, &req)==-1) {
    674             cli_out("ioctl SIOCSIFFLAGS error");
    675         }
    676         close(p->p_sock);
    677         p->p_sock = 0;
    678     }
    679     if (p->p_filterid > 0) {
    680         bcm_knet_filter_destroy(unit, p->p_filterid);
    681         p->p_filterid = 0;
    682     }
    683     
    684     if (p->p_netid > 0) {
    685         bcm_knet_netif_destroy(unit, p->p_netid);
    686         p->p_netid = 0;
    687     }
    688 }
    689 
    690 #endif
    691 
    692 /*
    693  * The following function may be called in interrupt context.
    694  * Does no packet classification; assume we're to see all pkts.
    695  */
    696 
    697 STATIC bcm_rx_t
    698 rpacket_rx_receive(int unit, bcm_pkt_t *pkt, void *vp)
    699 {
    700     p_t         *p = (p_t *)vp;
    701     int          send_len = p->p_pkt->_pkt_data.len;
    702     int          len = pkt->tot_len;
    703     if (!p->p_count_packets) {
    704         /*
    705          * Just drain packets.
    706          */
    707         p->p_drained++;
    708         return BCM_RX_HANDLED;
    709     }
    710 
    711     packet_measure(p, send_len, len, (uint8 *)pkt->pkt_data->data, 0);
    712 
    713     if (p->p_free_buffer) {
    714         if (p->p_intr_cb) { /* Queue in interrupt context */
    715             bcm_rx_free_enqueue(unit, pkt->_pkt_data.data);
    716         } else {
    717             bcm_rx_free(unit, pkt->alloc_ptr);
    718         }
    719         return BCM_RX_HANDLED_OWNED;
    720     }
    721 
    722     return BCM_RX_HANDLED;
    723 }
    724 
    725 STATIC INLINE int
    726 rpacket_register(int unit, p_t *p)
    727 {
    728     if (SOC_IS_ARAD(unit)) {
    729         return _bcm_common_rx_register(unit, "rpkt-rx", rpacket_rx_receive, RP_RECEIVER_PRIO, p, p->reg_flags);
    730 
    731     } else {
    732         return bcm_rx_register(unit, "rpkt-rx", rpacket_rx_receive,
    733                            RP_RECEIVER_PRIO, p, p->reg_flags);
    734     }
    735 }
    736 
    737 STATIC INLINE int
    738 rpacket_unregister(int unit, p_t *p)
    739 {
    740     if (SOC_IS_ARAD(unit)) {
    741         return _bcm_common_rx_unregister(unit, rpacket_rx_receive, RP_RECEIVER_PRIO);
    742     } else {
    743         return bcm_rx_unregister(unit, rpacket_rx_receive, RP_RECEIVER_PRIO);
    744     }
    745 }
    746 
    747 STATIC int
    748 rpacket_receiver_activate(int unit, p_t *p)
    749 {
    750     int rv;
    751 
    752     /* Set up common attributes first */
    753     if (bcm_rx_active(unit)) {
    754         cli_out("Stopping active RX.\n");
    755         rv = bcm_rx_stop(unit, NULL);
    756         if (!BCM_SUCCESS(rv)) {
    757             cli_out("Unable to stop RX: %s\n", bcm_errmsg(rv));
    758             return -1;
    759         }
    760     }
    761 
    762     if (!soc_feature(unit, soc_feature_packet_rate_limit)) {
    763         /* Only set the burst size if the unit doesn't have
    764          * CPU packet rate limiting feature in HW. Otherwise,
    765          * packets are dropped causing the test to fail.
    766          */
    767         if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit)) {
    768             rv = _bcm_common_rx_burst_set(unit, p->p_burst);
    769         } else {
    770             rv = bcm_rx_burst_set(unit, p->p_burst);
    771         }
    772         if (BCM_FAILURE(rv)) {
    773             cli_out("Unable to set RX burst limit: %s\n",
    774                     bcm_errmsg(rv));
    775         }
    776     }
    777 
    778     if (p->p_hw_rate) { 
    779         if (p->p_per_cos) {
    780             if (!SOC_IS_KATANA(unit)) {
    781                 bcm_rx_cos_rate_set(unit, 0, p->p_pkts_per_sec);
    782                 bcm_rx_cos_burst_set(unit, 0, p->p_burst);
    783                 p->p_rx_cfg.global_pps = 0;
    784                 p->p_rx_cfg.max_burst = 0;
    785             }
    786         } else {
    787             rv = bcm_port_rate_egress_pps_set (unit, CMIC_PORT(unit), 
    788                               p->p_pkts_per_sec, p->p_burst);
    789         } 
    790     } else {
    791             bcm_rx_cos_rate_set(unit, BCM_RX_COS_ALL, 0);
    792             bcm_rx_cos_burst_set(unit, BCM_RX_COS_ALL, 0);
    793             p->p_rx_cfg.global_pps = p->p_pkts_per_sec;
    794             p->p_rx_cfg.max_burst = p->p_burst;
    795     }  
    796     if (p->p_max_q_len >= 0) {
    797         cli_out("Setting MAX Q length to %d\n", p->p_max_q_len);
    798         bcm_rx_cos_max_len_set(unit, BCM_RX_COS_ALL, p->p_max_q_len);
    799     }
    800     if (SOC_IS_ARAD(unit)) {
    801         rv = _bcm_common_rx_start(unit, &p->p_rx_cfg  );
    802     } else {
    803         rv = bcm_rx_start(unit, &p->p_rx_cfg  );
    804     }
    805     if (!BCM_SUCCESS(rv)) {
    806         cli_out("Unable to Start RX: %s\n", bcm_errmsg(rv));
    807         return -1;
    808     }
    809     p->reg_flags = BCM_RCO_F_ALL_COS +
    810         (p->p_intr_cb ? BCM_RCO_F_INTR : 0);
    811 
    812     return 0;
    813 }
    814 
    815 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT)
    816 static int
    817 rp_dune_port_enable_set (int unit, p_t *p, int enable)
    818 {
    819     bcm_port_config_t config;
    820     pbmp_t      tmp_pbmp;
    821     int         port_idx;
    822     soc_port_t  port;
    823     int         rv = BCM_E_NONE;
    824 
    825     /** Disable all other ports */
    826     BCM_PBMP_ASSIGN(tmp_pbmp, PBMP_E_ALL(unit));
    827     /** Remove CPU port*/
    828     BCM_PBMP_REMOVE(tmp_pbmp, PBMP_CMIC(unit));
    829 
    830     /** Remove special ports that are not included in SOC PBMPCPU */
    831     rv = bcm_port_config_get(unit, &config);
    832     RP_CHK(rv, bcm_port_config_get);
    833     if (SOC_IS_DNX(unit))
    834     {
    835         BCM_PBMP_REMOVE(tmp_pbmp, config.erp);
    836         BCM_PBMP_REMOVE(tmp_pbmp, config.oamp);
    837         BCM_PBMP_REMOVE(tmp_pbmp, config.olp);
    838         BCM_PBMP_REMOVE(tmp_pbmp, config.eventor);
    839         BCM_PBMP_REMOVE(tmp_pbmp, config.sat);
    840         BCM_PBMP_REMOVE(tmp_pbmp, config.rcy_mirror);
    841     }
    842     else if (SOC_IS_ARAD(unit))
    843     {
    844         BCM_PBMP_REMOVE(tmp_pbmp, config.sat);
    845         BCM_PBMP_REMOVE(tmp_pbmp, config.ipsec);
    846     }
    847 
    848     /** Remove loopback ports */
    849     for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
    850         BCM_PBMP_PORT_REMOVE(tmp_pbmp, p->p_port[port_idx]);
    851     }
    852 
    853     PBMP_ITER(tmp_pbmp, port) {
    854         rv = bcm_port_enable_set(unit, port, enable);
    855         RP_CHK(rv, bcm_port_enable_set);
    856     }
    857 
    858     return rv;
    859 }
    860 static int
    861 rp_dune_get_ssp_and_cpu_channel(int unit, bcm_pkt_t *pkt, p_t *p)
    862 {
    863     int rv = BCM_E_NONE;
    864     uint32 flags;
    865     bcm_port_interface_info_t interface_info;
    866     bcm_port_mapping_info_t mapping_info;
    867     bcm_port_t port_ndx;
    868     bcm_port_t ptch_ssp = 0;
    869     bcm_core_t ptch_ssp_core = 0;
    870 
    871     /** Get corresponding core of PTCH.SSP */
    872     rv = bcm_port_get(unit, p->p_port[0], &flags, &interface_info, &mapping_info);
    873     RP_CHK(rv, bcm_port_get);
    874 
    875     /* ptch_ssp = mapping_info.pp_port; */
    876     ptch_ssp = p->p_port[0];
    877     ptch_ssp_core = mapping_info.core;
    878 
    879     /** Always set BCM_PKT_F_HGHDR to indicate MH is present*/
    880     p->p_pkt->flags |= BCM_PKT_F_HGHDR;
    881 
    882     /** Get first CPU port with Same core as in TM port*/
    883     BCM_PBMP_ITER(PBMP_CMIC(unit), port_ndx)
    884     {
    885         rv = bcm_port_get(unit, port_ndx, &flags, &interface_info, &mapping_info);
    886         if (rv != BCM_E_NONE)
    887         {
    888             test_error(unit, "bcm_port_get failed: %s\n", bcm_errmsg(rv));
    889         }
    890         if (mapping_info.core == ptch_ssp_core)
    891         {
    892             p->p_pkt->_dpp_hdr[0] = (uint8)(mapping_info.channel & 0xff);
    893             break;
    894         }
    895     }
    896 
    897     pkt->_dpp_hdr[1] = 0;
    898     pkt->_dpp_hdr[2] = 0;
    899     pkt->_dpp_hdr[3] = 0;
    900 
    901     /* Set SSP to PTCH */
    902     rp_ptch_header[1] = ptch_ssp;
    903 
    904     return rv;
    905 }
    906 
    907 #endif
    908 
    909 STATIC int
    910 rpacket_setup(int unit, p_t *p)
    911 {
    912     int         got_port;
    913     int         rv = BCM_E_UNAVAIL;
    914     uint8       *fill_addr;
    915     soc_port_t  port;
    916     int         port_idx;
    917     pbmp_t      gxe_pbm;
    918     pbmp_t      tmp_pbmp;
    919     int         speed = 0;
    920     int         txrx_modid = 0;
    921 
    922     p->p_txrx_unit = unit;
    923     p->p_use_fp_action = 0;
    924     p->p_num_test_ports = 1;
    925 
    926     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT2(unit) || SOC_IS_HELIX4(unit)){
    927         p->p_use_fp_action = 1;
    928         p->p_num_test_ports = 2;
    929     }
    930 
    931 #ifdef BCM_PETRA_SUPPORT
    932     if(SOC_IS_ARAD(unit)) {
    933         p->p_num_test_ports = 2;
    934     }
    935 #endif
    936 #ifdef BCM_DNX_SUPPORT
    937     if(SOC_IS_DNX(unit)) {
    938         p->p_num_test_ports = 2;
    939     }
    940 #endif
    941 
    942     /*
    943      * Pick a port, and redirect the packet back out that port with the
    944      * FFP. Single port redirection drops packets on ingress due to the
    945      * split horizon check
    946      */
    947 
    948     got_port = FALSE;
    949 
    950     BCM_PBMP_ASSIGN(gxe_pbm, PBMP_GE_ALL(unit));
    951     BCM_PBMP_OR(gxe_pbm, PBMP_XE_ALL(unit));
    952     BCM_PBMP_OR(gxe_pbm, PBMP_CE_ALL(unit));
    953 
    954     port_idx = 0;
    955     PBMP_ITER(gxe_pbm, port) {
    956         if (IS_ST_PORT(unit, port) || IS_PON_PORT(unit, port)) {
    957             continue;
    958         }
    959 #ifdef BCM_DNX_SUPPORT
    960         if (SOC_IS_DNX(unit))
    961         {
    962             rv = bcm_port_linkscan_get(unit, port, &p->p_port_info[port_idx].linkscan);
    963             RP_CHK(rv, bcm_port_linkscan_get);
    964             if (BCM_SUCCESS(rv))
    965             {
    966                 rv = bcm_port_linkscan_set(unit, port, BCM_LINKSCAN_MODE_NONE);
    967                 RP_CHK(rv, bcm_port_linkscan_set);
    968             }
    969             if (BCM_SUCCESS(rv))
    970             {
    971                 rv = bcm_port_loopback_get(unit, port, &p->p_port_info[port_idx].loopback);
    972                 RP_CHK(rv, bcm_port_loopback_get);
    973             }
    974         }
    975         else
    976 #endif
    977         {
    978             rv = bcm_port_info_save(unit, port, &p->p_port_info[port_idx]);
    979             RP_CHK(rv, bcm_port_info_save);
    980 
    981             if (BCM_SUCCESS(rv)) {
    982                 rv = bcm_port_linkscan_set(unit, port, BCM_LINKSCAN_MODE_NONE);
    983                 RP_CHK(rv, bcm_port_linkscan_set);
    984             }
    985 #ifdef BCM_PETRA_SUPPORT
    986             if ((SOC_IS_ARAD(unit) && SOC_DPP_PP_ENABLE(unit)) || (!SOC_IS_ARAD(unit)))
    987 #endif
    988             {
    989                 if (BCM_SUCCESS(rv))
    990                 {
    991                     rv = bcm_port_speed_max(unit, port, &speed);
    992                     RP_CHK(rv, bcm_port_speed_max);
    993                 }
    994 #ifdef BCM_TOMAHAWK3_SUPPORT
    995                 if (SOC_IS_TOMAHAWK3(unit) && IS_CD_PORT(unit, port) &&
    996                                              BCM_SUCCESS(rv))
    997                 {
    998                     bcm_port_resource_t pr;
    999                     BCM_IF_ERROR_RETURN(bcm_port_resource_get(unit, port, &pr));
   1000                     if (pr.speed != speed) {
   1001                         LOG_ERROR(BSL_LS_BCM_PORT,
   1002                                 (BSL_META_U(unit,
   1003                                  "port speed (%d) does NOT match "
   1004                                  " current speed (%d).\n"),
   1005                                  pr.speed, speed));
   1006                     }
   1007                     pr.speed = speed;
   1008                     BCM_IF_ERROR_RETURN(bcm_port_resource_speed_set(unit, port, &pr));
   1009                 }
   1010                 else
   1011 #endif
   1012                 {
   1013                     if (BCM_SUCCESS(rv))
   1014                     {
   1015                         rv = bcm_port_speed_set(unit, port, speed);
   1016                         RP_CHK(rv, bcm_port_speed_set);
   1017                     }
   1018                 }
   1019             }
   1020 
   1021             if (BCM_SUCCESS(rv)) {
   1022 #if defined(BCM_ESW_SUPPORT) || defined(BCM_FE2000_SUPPORT)
   1023                if (SOC_IS_HELIX4(unit)) {
   1024                    rv = bcm_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_PHY);
   1025                } else {
   1026                    rv = bcm_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_MAC);
   1027                }
   1028 #endif /* BCM_ESW_SUPPORT  || defined(BCM_FE2000_SUPPORT) */
   1029                RP_CHK(rv, bcm_port_loopback_set);
   1030             }
   1031             if (BCM_SUCCESS(rv)) {
   1032                 rv = bcm_port_pause_set(unit, port, 0, 0);
   1033                 RP_CHK(rv, bcm_port_pause_set);
   1034             }
   1035         }
   1036 
   1037         if ((got_port = BCM_SUCCESS(rv))) {
   1038             p->p_port[port_idx++] = port;
   1039 
   1040             if (port_idx >= p->p_num_test_ports) {
   1041                 break;
   1042             }
   1043             got_port = BCM_E_NOT_FOUND;
   1044         }
   1045     }
   1046 
   1047     if (!got_port) {
   1048         test_error(unit, "Unable to find suitable XE/GE port.\n");
   1049         return -1;
   1050     }
   1051 
   1052 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT)
   1053     if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit))
   1054     {
   1055         /* Disable all other ports */
   1056         rv = rp_dune_port_enable_set(unit, p, FALSE);
   1057         RP_CHK(rv, rp_dune_port_enable_set);
   1058     }
   1059     else
   1060 #endif
   1061     {
   1062         /* Disable all other ports (can run with active links plugged in) */
   1063         BCM_PBMP_ASSIGN(tmp_pbmp, PBMP_E_ALL(unit));
   1064 
   1065         /* Remove CPU port, it's not real ports for phy driver */
   1066         BCM_PBMP_REMOVE(tmp_pbmp, PBMP_CMIC(unit));
   1067         for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1068             BCM_PBMP_PORT_REMOVE(tmp_pbmp, p->p_port[port_idx]);
   1069         }
   1070 
   1071         PBMP_ITER(tmp_pbmp, port) {
   1072             rv = bcm_port_enable_set(unit, port, FALSE);
   1073             RP_CHK(rv, bcm_port_enable_set);
   1074         }
   1075     }
   1076 
   1077 #if defined(BCM_FIELD_SUPPORT)
   1078     if (soc_feature(unit, soc_feature_field)) {
   1079         if (SOC_IS_ESW(unit)) {
   1080 #if defined(BCM_ESW_SUPPORT) || defined(BCM_FE2000_SUPPORT)
   1081             bcm_field_qset_t        qset;
   1082             bcm_field_group_t       fg;
   1083             bcm_field_entry_t       fent[2];
   1084             int                     stat_id = -1;
   1085             bcm_field_stat_t        stat_type = bcmFieldStatPackets;
   1086 
   1087             BCM_FIELD_QSET_INIT(qset);
   1088             BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort);
   1089 
   1090             rv = bcm_field_group_create(unit, qset, BCM_FIELD_GROUP_PRIO_ANY, &fg);
   1091 
   1092             for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1093                 if (BCM_SUCCESS(rv)) {
   1094                     rv = bcm_field_entry_create(unit, fg, &fent[port_idx]);
   1095                 }
   1096 
   1097                 if (BCM_SUCCESS(rv)) {
   1098                     p->p_field_entry[port_idx] = fent[port_idx];
   1099 
   1100                     rv = bcm_field_qualify_InPort(unit, fent[port_idx],
   1101                                                   p->p_port[port_idx],
   1102                                                   BCM_FIELD_EXACT_MATCH_MASK);
   1103                 }
   1104             }
   1105 
   1106             if (BCM_SUCCESS(rv)) {
   1107                 for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1108                     rv = bcm_field_stat_create(unit, fg, 1, &stat_type, &stat_id);
   1109                     RP_CHK(rv, bcm_field_stat_create);
   1110 
   1111                     rv = bcm_field_entry_stat_attach(unit, fent[port_idx], stat_id);
   1112                     RP_CHK(rv, bcm_field_entry_stat_attach);
   1113                     stat_id = -1;
   1114                 }
   1115             }
   1116 
   1117             for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1118                 if (p->p_use_fp_action) {
   1119                     if (port_idx == 1) {
   1120                         if (BCM_SUCCESS(rv)) {
   1121                             rv = bcm_field_action_add(unit, fent[port_idx], 
   1122                                                       bcmFieldActionCopyToCpu,
   1123                                                       0, 0);
   1124                             RP_CHK(rv, bcm_field_action_add);
   1125                         }
   1126 #ifdef BCM_TOMAHAWK_SUPPORT
   1127                         if (SOC_IS_TOMAHAWKX(unit) && BCM_SUCCESS(rv)) {
   1128                             rv = bcm_field_action_add(unit, fent[port_idx], 
   1129                                                       bcmFieldActionDrop,
   1130                                                       0, 0);
   1131                             RP_CHK(rv, bcm_field_action_add);
   1132                         }
   1133 #endif /* BCM_TOMAHAWK_SUPPORT */
   1134                     }
   1135                 } else {
   1136                     if (BCM_SUCCESS(rv)) {
   1137                         rv = bcm_field_action_add(unit, fent[port_idx], 
   1138                                                   bcmFieldActionCopyToCpu,
   1139                                                   0, 0);
   1140                         RP_CHK(rv, bcm_field_action_add);
   1141                     }
   1142                 }
   1143                 if (BCM_SUCCESS(rv)) {
   1144 
   1145                     int port = p->p_port[port_idx];
   1146                     if (p->p_use_fp_action) {
   1147                         if (port_idx == 0) {
   1148                             rv = bcm_field_action_add(unit, fent[port_idx], 
   1149                                                   bcmFieldActionRedirect,
   1150                                                   0, port);
   1151                             RP_CHK(rv, bcm_field_action_add);
   1152 
   1153                             rv = bcm_field_action_add(unit, fent[port_idx], 
   1154                                                   bcmFieldActionMirrorEgress,
   1155                                                   0, p->p_port[1]);
   1156                             RP_CHK(rv, bcm_field_action_add);
   1157 
   1158                         }
   1159                     } else {
   1160                         rv = bcm_field_action_add(unit, fent[port_idx], 
   1161                                                   bcmFieldActionRedirect,
   1162                                                   0, port);
   1163                         RP_CHK(rv, bcm_field_action_add);
   1164                     }
   1165                 }
   1166             }
   1167 #endif /* BCM_ESW_SUPPORT || BCM_FE2000_SUPPORT */
   1168         } else {
   1169         }
   1170     }
   1171 
   1172 #endif /* BCM_FIELD_SUPPORT */
   1173     if (BCM_FAILURE(rv)) {
   1174         test_error(unit, "Unable to configure filter: %s\n", bcm_errmsg(rv));
   1175         return -1;
   1176     }
   1177 
   1178 #ifdef BCM_DNX_SUPPORT
   1179     if (SOC_IS_DNX(unit))
   1180     {
   1181         for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1182             /* coverity [returned_value] */
   1183             rv = bcm_port_learn_set(unit, p->p_port[port_idx], BCM_PORT_LEARN_FWD);
   1184             RP_CHK(rv, bcm_port_learn_set);
   1185         }
   1186     }
   1187     else
   1188 #endif     
   1189     {
   1190         /* Disable learning on that port */
   1191 #ifdef BCM_PETRA_SUPPORT
   1192         if ((SOC_IS_ARAD(unit) && SOC_DPP_PP_ENABLE(unit)) || (!SOC_IS_ARAD(unit)))
   1193 #endif
   1194         {
   1195             for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1196                 /* coverity [returned_value] */
   1197                 rv = bcm_port_learn_set(unit, p->p_port[port_idx], BCM_PORT_LEARN_FWD);
   1198                 RP_CHK(rv, bcm_port_learn_set);
   1199             }
   1200         }
   1201     }
   1202 
   1203     /* Create Maximum size packet requested */
   1204     BCM_IF_ERROR_RETURN(bcm_pkt_alloc(p->p_txrx_unit , p->p_l_end, 0, &(p->p_pkt)));
   1205     if (p->p_pkt == NULL) {
   1206         test_error(unit, "Failed to allocate Tx packet\n");
   1207         return -1;
   1208     }
   1209 
   1210     p->p_pkt->flags = BCM_TX_CRC_REGEN;
   1211 
   1212 #ifdef BCM_PETRA_SUPPORT
   1213     if (SOC_IS_ARAD(unit))
   1214     {
   1215         rv = rp_dune_get_ssp_and_cpu_channel(unit, p->p_pkt, p);
   1216         RP_CHK(rv, rp_dune_get_ssp_and_cpu_channel);
   1217 
   1218         p->p_pkt->flags |= BCM_TX_CRC_APPEND;
   1219 
   1220         /* Fill in buffer */
   1221         SOC_DPP_PKT_PTCH_HDR_SET(p->p_pkt, rp_ptch_header);
   1222         SOC_DPP_PKT_HDR_DMAC_SET_WITH_PTCH(p->p_pkt, rp_mac_dest);
   1223         SOC_DPP_PKT_HDR_SMAC_SET_WITH_PTCH(p->p_pkt, rp_mac_src);
   1224         SOC_DPP_PKT_HDR_TPID_SET_WITH_PTCH(p->p_pkt, ENET_DEFAULT_TPID);
   1225         SOC_DPP_PKT_HDR_VTAG_CONTROL_SET_WITH_PTCH(p->p_pkt, VLAN_CTRL(0, 0, 1));
   1226         /* Fill address starts at PTCH(2) + DMAC(6) + SMAC(6) + VTAG(4) */
   1227         fill_addr = BCM_PKT_DMAC(p->p_pkt) + 2 + 6 + 6 + 4;
   1228 
   1229         sal_memcpy(fill_addr, mypacket, p->p_l_end - (fill_addr - BCM_PKT_DMAC(p->p_pkt)));
   1230     }
   1231     else
   1232 #endif
   1233 #ifdef BCM_DNX_SUPPORT
   1234     if (SOC_IS_DNX(unit)) {
   1235         rv = rp_dune_get_ssp_and_cpu_channel(unit, p->p_pkt, p);
   1236         RP_CHK(rv, rp_dune_get_ssp_and_cpu_channel);
   1237 
   1238         /** Disable visibility resume which lower down PPS/BPS */
   1239         p->p_pkt->flags |= BCM_TX_NO_VISIBILITY_RESUME;
   1240 
   1241         /* Fill in buffer */
   1242         RP_DNX_PKT_MH_HDR_SET(p->p_pkt, rp_mh_header);
   1243         RP_DNX_PKT_PTCH_HDR_SET_WITH_MH(p->p_pkt, rp_ptch_header);
   1244         RP_DNX_PKT_HDR_DMAC_SET_WITH_MH_PTCH(p->p_pkt, rp_mac_dest);
   1245         RP_DNX_PKT_HDR_SMAC_SET_WITH_MH_PTCH(p->p_pkt, rp_mac_src);
   1246         RP_DNX_PKT_HDR_TPID_SET_WITH_MH_PTCH(p->p_pkt, ENET_DEFAULT_TPID);
   1247         RP_DNX_PKT_HDR_VTAG_CONTROL_SET_WITH_MH_PTCH(p->p_pkt, VLAN_CTRL(0, 0, 1));
   1248         /* Fill address starts at MH(16) + PTCH(2) + DMAC(6) + SMAC(6) + VTAG(4) */
   1249         fill_addr = BCM_PKT_DMAC(p->p_pkt) + DNX_MODULE_HEADER_SIZE + RP_DNX_HDR_PTCH_TYPE2_LEN + RP_DNX_MAC_ADDR_LEN + RP_DNX_MAC_ADDR_LEN + sizeof(uint32);
   1250         sal_memcpy(fill_addr, mypacket, p->p_l_end - (fill_addr - BCM_PKT_DMAC(p->p_pkt)));
   1251     }
   1252     else 
   1253 #endif
   1254     {
   1255         /* Fill in buffer */
   1256         BCM_PKT_HDR_DMAC_SET(p->p_pkt, rp_mac_dest);
   1257         BCM_PKT_HDR_SMAC_SET(p->p_pkt, rp_mac_src);
   1258         BCM_PKT_HDR_TPID_SET(p->p_pkt, ENET_DEFAULT_TPID);
   1259         BCM_PKT_HDR_VTAG_CONTROL_SET(p->p_pkt, VLAN_CTRL(0, 0, 1));
   1260         /* Fill address starts 2 * MAC + TPID + VTAG */
   1261         fill_addr = BCM_PKT_DMAC(p->p_pkt) + 6 + 6 + 2 + 2;
   1262         sal_memset(fill_addr, 0xff, p->p_l_end -
   1263                    (fill_addr - BCM_PKT_DMAC(p->p_pkt)));
   1264     }
   1265 
   1266     /* Set the dest port for the packet 
   1267      *  For all devices, the packet will target the first port
   1268      */
   1269     BCM_PKT_PORT_SET(p->p_pkt, p->p_port[0], FALSE, FALSE);
   1270     p->p_pkt->dest_mod = txrx_modid;
   1271     p->p_pkt->opcode = BCM_PKT_OPCODE_UC;
   1272 
   1273     /* Set up the proper configuration */
   1274     rv = rpacket_receiver_activate(p->p_txrx_unit, p);
   1275     if (!BCM_SUCCESS(rv)) {
   1276         test_error(unit, "Could not setup receiver\n");
   1277         return -1;
   1278     }
   1279 
   1280     return 0;
   1281 }
   1282 
   1283 /*
   1284  * Function:
   1285  *      rpacket_storm_start
   1286  * Purpose:
   1287  *      Start packet storm in switch to serve as packet generator
   1288  * Parameters:
   1289  *      u - unit #.
   1290  *      p - pointer to test parameters
   1291  *      l - length of packet to send
   1292  * Returns:
   1293  *      0 on success, -1 on failure
   1294  * Notes:
   1295 */
   1296 
   1297 int
   1298 rpacket_storm_start (int unit, p_t *p, int l)
   1299 {
   1300     int rv = 0;
   1301     int tx_pkt_idx;
   1302     int tx_pkt_cnt = 1;
   1303 
   1304 #if defined(BCM_FIELD_SUPPORT)
   1305     if (soc_feature(unit, soc_feature_field)) {
   1306         int port_idx = 0;
   1307         if (SOC_IS_ESW(unit)) {
   1308             for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1309                 rv = bcm_field_entry_install(unit, p->p_field_entry[port_idx]);
   1310                 RP_CHK(rv, bcm_field_entry_install);
   1311             }
   1312         } else {
   1313         }
   1314     }
   1315 #endif
   1316 
   1317     if (BCM_FAILURE(rv)) {
   1318         test_error(unit, "Unable to install filter: %s\n", bcm_errmsg(rv));
   1319         return rv;
   1320     }
   1321 
   1322     /* determine num packets needed to test this architecture */
   1323 
   1324     /* set up test ports */
   1325 
   1326     /* Send packet(s) to kick off packet storm */
   1327 #ifdef BCM_PETRA_SUPPORT
   1328     if (SOC_IS_ARAD(unit))
   1329     {
   1330         /** include 2 bytes PTCH */
   1331         BCM_PKT_TX_LEN_SET(p->p_pkt, (l + 2));
   1332     }
   1333     else
   1334 #endif
   1335 #ifdef BCM_DNX_SUPPORT
   1336     if (SOC_IS_DNX(unit))
   1337     {
   1338         /** exclude 16bytes MH and 2 bytes PTCH */
   1339         BCM_PKT_TX_LEN_SET(p->p_pkt, (l + DNX_MODULE_HEADER_SIZE + 2));
   1340     }
   1341     else
   1342 #endif
   1343     {
   1344         BCM_PKT_TX_LEN_SET(p->p_pkt, l);
   1345     }
   1346 #ifdef BCM_PETRA_SUPPORT
   1347     if (SOC_IS_ARAD(unit)) {
   1348         int port_idx;
   1349         SOC_DPP_PKT_HDR_TAGGED_LEN_SET_WITH_PTCH(p->p_pkt, l); /* Set length */
   1350         if (SOC_IS_ARADPLUS_AND_BELOW(unit)) {
   1351             uint32 reg_val = 0;
   1352             READ_IPT_FORCE_LOCAL_OR_FABRICr(unit,  &reg_val);
   1353             is_force_fabric = soc_reg_field_get(unit, IPT_FORCE_LOCAL_OR_FABRICr, reg_val, FORCE_FABRICf);
   1354             is_force_local = soc_reg_field_get(unit, IPT_FORCE_LOCAL_OR_FABRICr, reg_val, FORCE_LOCALf);
   1355             soc_reg_field_set(unit, IPT_FORCE_LOCAL_OR_FABRICr, &reg_val, FORCE_FABRICf, 0);
   1356             soc_reg_field_set(unit, IPT_FORCE_LOCAL_OR_FABRICr, &reg_val, FORCE_LOCALf, 1);
   1357             WRITE_IPT_FORCE_LOCAL_OR_FABRICr(unit,  reg_val);
   1358         }
   1359         /** Set Loopback to make packet storm  */
   1360         for (port_idx = 0; port_idx < p->p_num_test_ports; port_idx++)
   1361         {
   1362             rv = bcm_port_loopback_set(unit, p->p_port[port_idx], BCM_PORT_LOOPBACK_MAC);
   1363             RP_CHK(rv, bcm_port_loopback_set);
   1364         }
   1365     }
   1366     else 
   1367 #endif
   1368 #ifdef BCM_DNX_SUPPORT
   1369     if (SOC_IS_DNX(unit)) {
   1370         int port_idx;
   1371         /** Set Loopback to make packet storm  */
   1372         for (port_idx = 0; port_idx < p->p_num_test_ports; port_idx++)
   1373         {
   1374         rv = bcm_port_loopback_set(unit, p->p_port[port_idx], BCM_PORT_LOOPBACK_MAC);
   1375         RP_CHK(rv, bcm_port_loopback_set);
   1376         }
   1377     }
   1378     else
   1379 #endif
   1380     {
   1381         BCM_PKT_HDR_TAGGED_LEN_SET(p->p_pkt, l); /* Set length */
   1382     }
   1383 
   1384     for (tx_pkt_idx = 0; tx_pkt_idx < tx_pkt_cnt; tx_pkt_idx++) {
   1385 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1386         if (SOC_KNET_MODE(unit) && p->p_use_socket_send) {
   1387             rv = send (p->p_sock, p->p_pkt->_pkt_data.data, l, 0);
   1388             if (rv < 0) { 
   1389                 cli_out("Send to socket %d returned len %d errno %d\n", 
   1390                 p->p_sock, rv, errno);
   1391                 rv = BCM_E_FAIL;
   1392             }
   1393         } else
   1394 #endif 
   1395         {
   1396             rv = bcm_tx(p->p_txrx_unit, p->p_pkt, NULL);
   1397         }
   1398     }
   1399 
   1400     return rv;
   1401 } /* rpacket_storm_start */
   1402 
   1403  /*
   1404   * Function:
   1405   *      rpacket_storm_stop
   1406   * Purpose:
   1407   *      Stop packet storm; clear out remaining packets
   1408   * Parameters:
   1409   *      u - unit #.
   1410   *      p - pointer to test parameters
   1411   * Returns:
   1412   *      0 on success, -1 on failure
   1413   * Notes:
   1414   */
   1415  int
   1416  rpacket_storm_stop (int unit, p_t *p)
   1417 {
   1418     int rv = 0;
   1419 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT)
   1420     int port_index;
   1421 #endif
   1422 
   1423 /*
   1424  * Stop the packets from flowing.
   1425  */
   1426 #if defined(BCM_FIELD_SUPPORT)
   1427     if (soc_feature(unit, soc_feature_field)) {
   1428         int port_idx = 0;
   1429         if (SOC_IS_ESW(unit)) {
   1430             for (port_idx=0; port_idx < p->p_num_test_ports; port_idx++) {
   1431                 rv = bcm_field_entry_remove(unit, p->p_field_entry[port_idx]);
   1432                 RP_CHK(rv, bcm_field_entry_remove);
   1433             }
   1434         } else {
   1435         }
   1436         }
   1437 #endif
   1438     if (BCM_FAILURE(rv)) {
   1439         test_error(unit, "Unable to remove filter: %s\n", bcm_errmsg(rv));
   1440         return rv;
   1441     }
   1442 
   1443 #ifdef BCM_PETRA_SUPPORT
   1444     if (SOC_IS_ARADPLUS_AND_BELOW(unit)) {
   1445         uint32 reg_val = 0;
   1446         READ_IPT_FORCE_LOCAL_OR_FABRICr(unit,  &reg_val);
   1447         soc_reg_field_set(unit, IPT_FORCE_LOCAL_OR_FABRICr, &reg_val, FORCE_FABRICf, is_force_fabric);
   1448         soc_reg_field_set(unit, IPT_FORCE_LOCAL_OR_FABRICr, &reg_val, FORCE_LOCALf, is_force_local);
   1449         WRITE_IPT_FORCE_LOCAL_OR_FABRICr(unit,  reg_val);
   1450     }
   1451     /** Clear Loopback to stop packet storm  */
   1452     for (port_index = 0; port_index < p->p_num_test_ports; port_index++)
   1453     {
   1454         rv = bcm_port_loopback_set(unit, p->p_port[port_index], BCM_PORT_LOOPBACK_NONE);
   1455         RP_CHK(rv, bcm_port_loopback_set);
   1456     }
   1457 #endif
   1458 #ifdef BCM_DNX_SUPPORT
   1459     if (SOC_IS_DNX(unit)) {
   1460         /** Clear Loopback to stop packet storm  */
   1461         for (port_index = 0; port_index < p->p_num_test_ports; port_index++)
   1462         {
   1463             rv = bcm_port_loopback_set(unit, p->p_port[port_index], BCM_PORT_LOOPBACK_NONE);
   1464             RP_CHK(rv, bcm_port_loopback_set);
   1465         }
   1466     }
   1467 #endif
   1468 
   1469     return rv;
   1470 } /* rpacket_storm_stop */
   1471 
   1472 /*
   1473  * Function:
   1474  *      rpacket_test
   1475  * Purpose:
   1476  *      Test packet reception interface.
   1477  * Parameters:
   1478  *      u - unit #.
   1479  *      a - pointer to arguments.
   1480  *      pa - ignored cookie.
   1481  * Returns:
   1482  *      0 on success, -1 on failure
   1483  * Notes:
   1484  *      There remains an issue when stealing packets that the
   1485  *      system will crash when the rate is high enough.  This has
   1486  *      been experimentally determined to be between 4-5K pkts/sec
   1487  *      on Mousse (8240) and 6-7K pkts/sec on BMW (8245).
   1488  */
   1489 
   1490 int
   1491 rpacket_test(int unit, args_t *a, void *pa)
   1492 {
   1493     p_t *p = (p_t *)pa;
   1494     int l, rv = BCM_E_UNAVAIL;
   1495     int test_rv = 0;
   1496     int use_socket  = 0;
   1497     int ringbuf_size = 0;
   1498     sal_cpu_stats_t  cpu_start;
   1499     sal_cpu_stats_t  cpu_end;
   1500 
   1501 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 
   1502     long unsigned int knet_pkt=0;
   1503     long unsigned int knet_ic =0;
   1504 #endif
   1505     soc_control_t    *soc = SOC_CONTROL(unit);
   1506     int desc_intr_count = 0;
   1507     int chain_intr_count = 0;    
   1508 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 
   1509     if (SOC_KNET_MODE(unit)) {
   1510         use_socket = p->p_use_socket;
   1511         ringbuf_size = p->p_ringbuf_size ;
   1512     }
   1513 #endif    
   1514     /* coverity[dead_error_condition] */
   1515     cli_out("\n"
   1516             "Rate: %d/%d (%s). %s %s. %s %d PPC. Packets%s freed.\n",
   1517             p->p_pkts_per_sec,
   1518             p->p_burst,
   1519             p->p_hw_rate  ? "HW" : "SW",
   1520             "IF:",
   1521             use_socket ? 
   1522             (ringbuf_size ? "ring" : "socket") :
   1523             "bcm_rx",
   1524             (use_socket) ? "" : ((p->p_intr_cb) ? "Intr CB." : "Task CB."),
   1525             p->p_rx_cfg.pkts_per_chain,
   1526             p->p_free_buffer ? "" : " not"
   1527             );
   1528 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1529     if (SOC_KNET_MODE(unit)) {
   1530         cli_out("\n"
   1531                 "  Packet |          Rate           |  Total    |         | CPU %%             | Knet tot  Knet Rate |\n"
   1532                 "   Len   |   Pkt/s   |    MB/s     |  packets  |  Time   | Idle /user /kern  |  packets | Pkt/s    |Interrupts\n"
   1533                 " --------+-----------+-------------+-----------+---------+-------------------+----------+----------+----------\n");
   1534     } else
   1535 #endif
   1536     {
   1537         cli_out("\n"
   1538                 "  Packet |          Rate           |  Total    |         | CPU %%             |    Interrupts\n"
   1539                 "   Len   |   Pkt/s   |    MB/s     |  packets  |  Time   | Idle /user /kern  | Desc_Intr|Chain_Intr\n"
   1540                 " --------+-----------+-------------+-----------+---------+-------------------+----------+----------\n");
   1541     }
   1542 
   1543     if (!use_socket) {
   1544             /* Register the callback handler */
   1545             rv = rpacket_register(p->p_txrx_unit, p);
   1546             if (BCM_FAILURE(rv)) {
   1547                 test_error(unit, "Unable to register handler, %s\n",
   1548                             bcm_errmsg(rv));
   1549                 test_rv = -1;
   1550                 goto done;
   1551             }
   1552     }
   1553 
   1554     for (l = p->p_l_start; l <= p->p_l_end; l += p->p_l_inc) {
   1555 
   1556         if (SOC_IS_KATANA(unit) && p->p_hw_rate)  {
   1557             bcm_port_rate_egress_set(unit, CMIC_PORT(unit), 
   1558                                       p->p_pkts_per_sec * l / 125, p->p_burst * l /125);
   1559         }
   1560 
   1561         rv = rpacket_storm_start (unit, p, l);
   1562         if (BCM_FAILURE(rv)) {
   1563             test_error(unit, "Failed to start packet storm: %s\n", bcm_errmsg(rv));
   1564             test_rv = -1;
   1565             goto done;
   1566         }
   1567 
   1568         /* Start clean */
   1569         p->p_received = 0;
   1570         p->p_drained = 0;
   1571         p->p_time_us = 0;
   1572         p->p_error_num = 0;
   1573 
   1574         /* measure rx packets over known interval*/
   1575 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1576         if (SOC_KNET_MODE(unit)) {
   1577             knet_stats_clear();
   1578         }
   1579 #endif
   1580         sal_cpu_stats_get (&cpu_start);
   1581         desc_intr_count = soc->stat.intr_desc;
   1582         chain_intr_count =  soc->stat.intr_chain;
   1583         p->p_count_packets = TRUE;
   1584         sal_sleep(p->p_time);
   1585         p->p_count_packets = FALSE;
   1586         desc_intr_count = soc->stat.intr_desc - desc_intr_count;
   1587         chain_intr_count = soc->stat.intr_chain - chain_intr_count;
   1588 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1589         if (SOC_KNET_MODE(unit)) {
   1590             knet_stats_get(&knet_ic, &knet_pkt);
   1591         }
   1592 #endif
   1593         sal_cpu_stats_get (&cpu_end);
   1594 
   1595         rv = rpacket_storm_stop (unit, p);
   1596         if (BCM_FAILURE(rv)) {
   1597             test_error(unit, "Failed to stop packet storm: %s\n", bcm_errmsg(rv));
   1598             test_rv = -1;
   1599             goto done;
   1600         }
   1601 
   1602         /* display test results */
   1603         {
   1604             int td, bps, pps, idle, user,kernel ;
   1605             int idle_diff, user_diff, kernel_diff, total_diff;
   1606 
   1607             td = (p->p_time_us + 500UL) / 1000UL; /* round to ms */
   1608             if (td == 0) { /* avoid divide by zero */
   1609                 td = 1;
   1610             }
   1611             if (p->p_received == 0) {
   1612                 pps = bps = 0;
   1613             } else {
   1614                 pps = (1000UL * p->p_received) / td;
   1615                 bps = (p->p_received * l) / td;
   1616             }
   1617 
   1618             COMPILER_64_SUB_64(cpu_end.total, cpu_start.total);
   1619             total_diff = (int)(u64_L(cpu_end.total));
   1620             COMPILER_64_SUB_64(cpu_end.idle, cpu_start.idle);
   1621             idle_diff = (int)(u64_L(cpu_end.idle));
   1622             COMPILER_64_SUB_64(cpu_end.user, cpu_start.user);
   1623             user_diff = (int)(u64_L(cpu_end.user));
   1624             COMPILER_64_SUB_64(cpu_end.kernel, cpu_start.kernel);
   1625             kernel_diff = (int)(u64_L(cpu_end.kernel));
   1626 
   1627             if (total_diff != 0) {
   1628                 idle = idle_diff * 10000UL / total_diff;
   1629                 user = user_diff * 10000UL / total_diff;
   1630                 kernel = kernel_diff * 10000UL / total_diff;
   1631             } else {
   1632                 idle = 0;
   1633                 user = 0;
   1634                 kernel = 0;
   1635             }
   1636 
   1637 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1638             if (SOC_KNET_MODE(unit)) {
   1639                 cli_out("  %5u  | %8u  | %5u.%03u   | %8u  | %3u.%03u | %2u.%02u/%2u.%02u/%2u.%02u | %8lu | %8u | %8lu ",
   1640                         l,
   1641                         (int)pps,
   1642                         (int)(bps / 1000), (int)(bps % 1000),
   1643                         p->p_received,
   1644                         td / 1000, td % 1000,
   1645                         idle / 100, idle % 100,
   1646                         user / 100, user % 100,
   1647                         kernel / 100, kernel % 100,
   1648                         knet_pkt, (td < p->p_time*1000) ? (int)(knet_pkt/p->p_time): (int)((knet_pkt * 1000) / td), knet_ic);
   1649             } else
   1650 #endif
   1651             {
   1652                 cli_out("  %5u  | %8u  | %5u.%03u   | %8u  | %3u.%03u | %2u.%02u/%2u.%02u/%2u.%02u | %8u | %8u ",
   1653                         l,
   1654                         (int)pps,
   1655                         (int)(bps / 1000), (int)(bps % 1000),
   1656                         p->p_received,
   1657                         td / 1000, td % 1000,
   1658                         idle / 100, idle % 100,
   1659                         user / 100, user % 100,
   1660                         kernel / 100, kernel % 100,
   1661                         desc_intr_count, chain_intr_count);
   1662             }
   1663 
   1664             if (p->p_error_num > 0) {
   1665                 cli_out(" e:%d \n", p->p_error_num);
   1666             } else {
   1667                 cli_out("\n");
   1668             }
   1669         }
   1670          /* Sleep a bit to let current backlog of packets drain */
   1671         sal_sleep(2);
   1672 
   1673     }
   1674 
   1675     if (!use_socket) {
   1676             /* Unregister the handler, let discard take over */
   1677             rv = rpacket_unregister(p->p_txrx_unit, p);
   1678             if (BCM_FAILURE(rv)) {
   1679                 test_error(unit, "Unable to unregister handler, %s\n",
   1680                            bcm_errmsg(rv));
   1681                 test_rv = -1;
   1682                 goto done;
   1683             }
   1684     }
   1685 
   1686 done:
   1687     if (p->p_dump_rx) {
   1688 #ifdef  BROADCOM_DEBUG
   1689         bcm_rx_show(unit);
   1690 #endif  /* BROADCOM_DEBUG */
   1691     }
   1692     return test_rv;
   1693 }
   1694 
   1695 
   1696 STATIC int
   1697 rpacket_receiver_deactivate(int unit, p_t *p)
   1698 {
   1699 #ifdef BCM_DNX_SUPPORT
   1700     int rv;
   1701     if(SOC_IS_DNX(unit)) {
   1702     if (bcm_rx_active(unit)) {
   1703         cli_out("Stopping active RX.\n");
   1704         rv = bcm_rx_stop(unit, NULL);
   1705         if (!BCM_SUCCESS(rv)) {
   1706             cli_out("Unable to stop RX: %s\n", bcm_errmsg(rv));
   1707             return -1;
   1708         }
   1709     }
   1710 
   1711     rv = dnx_rx_appl_active(unit);
   1712     if (!BCM_SUCCESS(rv)) {
   1713         cli_out("Unable to active RX: %s\n", bcm_errmsg(rv));
   1714         return -1;
   1715     }
   1716     }
   1717 #endif
   1718     return 0;
   1719 }
   1720 
   1721 
   1722 
   1723 /*ARGSUSED*/
   1724 int
   1725 rpacket_done(int unit, void *pa)
   1726 /*
   1727  * Function:    rpacket_done
   1728  * Purpose:     Clean up after rpacket test.
   1729  * Parameters:  unit - unit #
   1730  *              pa - cookie (as returned by rpacket_init();
   1731  * Returns:     0 - OK
   1732  *              -1 - failed
   1733  */
   1734 {
   1735     p_t         *p = p_control[unit];
   1736     int         rv;
   1737     int         port_idx;
   1738 
   1739     if (p == NULL) {
   1740         return 0;
   1741     }
   1742 
   1743     if (p->p_pkt != NULL) {
   1744         bcm_pkt_free(unit, p->p_pkt);
   1745         p->p_pkt = NULL;
   1746     }
   1747 
   1748     rv = rpacket_receiver_deactivate(p->p_txrx_unit, p);
   1749     if (BCM_FAILURE(rv)) {
   1750         test_error(unit, "Unable to deactivate receiver.\n");
   1751         return -1;
   1752     }
   1753 
   1754 #ifdef BCM_DNX_SUPPORT
   1755     if (SOC_IS_DNX(unit))
   1756     {
   1757         /* Restore port */
   1758         for (port_idx = 0; port_idx < p->p_num_test_ports; port_idx++)
   1759         {
   1760             rv = bcm_port_linkscan_set(unit, p->p_port[port_idx], p->p_port_info[port_idx].linkscan);
   1761             RP_CHK(rv, bcm_port_loopback_set);
   1762             rv = bcm_port_loopback_set(unit, p->p_port[port_idx], p->p_port_info[port_idx].loopback);
   1763             RP_CHK(rv, bcm_port_loopback_set);
   1764         }
   1765 
   1766         /* Enable all other ports */
   1767         rv = rp_dune_port_enable_set(unit, p, TRUE);
   1768         RP_CHK(rv, rp_dune_port_enable_set);
   1769     }
   1770     else
   1771 #endif
   1772 #ifdef BCM_PETRA_SUPPORT
   1773     if (SOC_IS_JERICHO(unit))
   1774     {
   1775         int         ms;
   1776         /* Restore port */
   1777         for (port_idx = 0; port_idx < p->p_num_test_ports; port_idx++) {
   1778             /* If the Master mode is not changed, remove phy_master attributes from action_mask */
   1779             ms = 0;
   1780             if ((rv = bcm_port_master_get(unit, p->p_port[port_idx], &ms)) != BCM_E_NONE) {
   1781                 cli_out("rpacket_done: port %s: could not get port Master mode: %s\n",
   1782                         SOC_PORT_NAME(unit, p->p_port[port_idx]),
   1783                         bcm_errmsg(rv));
   1784                 return -1;
   1785             }
   1786             if (ms == p->p_port_info[port_idx].phy_master) {
   1787                p->p_port_info[port_idx].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   1788             }
   1789 
   1790             rv = bcm_port_info_restore(unit, p->p_port[port_idx],
   1791                                        &p->p_port_info[port_idx]);
   1792             if (BCM_FAILURE(rv)) {
   1793                 test_error(unit, "Unable to restore port %d: %s\n",
   1794                            p->p_port[port_idx], bcm_errmsg(rv));
   1795                 return -1;
   1796             }
   1797         }
   1798         /* Enable all other ports */
   1799         rv = rp_dune_port_enable_set(unit, p, TRUE);
   1800         RP_CHK(rv, rp_dune_port_enable_set);
   1801     }
   1802     else if (SOC_IS_ARADPLUS_AND_BELOW(unit))
   1803     {
   1804         /* Restore port */
   1805         for (port_idx = 0; port_idx < p->p_num_test_ports; port_idx++)
   1806         {
   1807             rv = bcm_port_info_restore(unit, p->p_port[port_idx],
   1808                                        &p->p_port_info[port_idx]);
   1809             if (BCM_FAILURE(rv)) {
   1810                 test_error(unit, "Unable to restore port %d: %s\n",
   1811                            p->p_port[port_idx], bcm_errmsg(rv));
   1812                 return -1;
   1813             }
   1814         }
   1815         /* Enable all other ports */
   1816         rv = rp_dune_port_enable_set(unit, p, TRUE);
   1817         RP_CHK(rv, rp_dune_port_enable_set);
   1818     }
   1819     else
   1820 #endif
   1821     {
   1822         int         ms;
   1823         /* Restore port */
   1824         for (port_idx = 0; port_idx < p->p_num_test_ports; port_idx++) {
   1825             /* If the Master mode is not changed, remove phy_master attributes from action_mask */
   1826             ms = 0;
   1827             if ((rv = bcm_port_master_get(unit, p->p_port[port_idx], &ms)) != BCM_E_NONE) {
   1828                 cli_out("rpacket_done: port %s: could not get port Master mode: %s\n",
   1829                         SOC_PORT_NAME(unit, p->p_port[port_idx]),
   1830                         bcm_errmsg(rv));
   1831                 return -1;
   1832             }
   1833             if (ms == p->p_port_info[port_idx].phy_master) {
   1834                p->p_port_info[port_idx].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   1835             }
   1836 
   1837             rv = bcm_port_info_restore(unit, p->p_port[port_idx],
   1838                                        &p->p_port_info[port_idx]);
   1839             if (BCM_FAILURE(rv)) {
   1840                 test_error(unit, "Unable to restore port %d: %s\n",
   1841                            p->p_port[port_idx], bcm_errmsg(rv));
   1842                 return -1;
   1843             }
   1844         }
   1845 
   1846     }
   1847 
   1848     /*
   1849      * Try to remove filter, ignore error since we don't know how far
   1850      * we got in initialization.
   1851      */
   1852 #if defined(BCM_FIELD_SUPPORT)
   1853     if (soc_feature(unit, soc_feature_field)) {
   1854         int i = 0;
   1855         if (SOC_IS_ESW(unit)) {
   1856             for (i = 0; i < p->p_num_test_ports; i++) {
   1857                 rv = bcm_field_entry_remove(unit, p->p_field_entry[i]);
   1858                 RP_CHK(rv, bcm_field_entry_remove);
   1859                 rv = bcm_field_entry_destroy(unit, p->p_field_entry[i]);
   1860                 RP_CHK(rv, bcm_field_entry_destroy);
   1861             }
   1862         } else {
   1863         }
   1864     }
   1865 #endif
   1866 
   1867 
   1868     /*
   1869      * Don't free the p_control entry,
   1870      * keep it around to save argument state
   1871      */
   1872      
   1873 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1874     if (SOC_KNET_MODE(unit)) {
   1875         knetif_clean(unit, p);
   1876     }
   1877 #endif
   1878     return 0;
   1879 }
   1880 
   1881 char rpacket_usage[] = 
   1882 "Receive Packet Test Usage:\n"
   1883 #ifndef COMPILER_STRING_CONST_LIMIT
   1884 "  Time=<value>         : Specify the test duration for each packet length. (default=2)\n"
   1885 "  LengthStart=<value>  : Specify the start pakcet length. (default=64)\n"
   1886 "  LengthEnd=<value>    : Specify the end pakcet length. (default=1522)\n"
   1887 "  LengthInc=<value>    : Specify the increasing step of pakcet length. (default=64)\n"
   1888 "  FreeBuffer=<value>   : Indicate if packet buffer will be freed. (default=FALSE)\n"
   1889 "  QLen=<value>         : Specify Max number of packets permitted in cos queue. (default=200)\n"
   1890 "  PERCos=<value>       : Indicate if test is running with per-cos settings. (default=FALSE)\n"
   1891 "  Rate=<value>         : Specify packets per second for a cos queue. (default=0)\n"
   1892 "  Burst=<value>        : Specify packets to be received in a single burst. (default=100)\n"
   1893 "  HWrate=<value>       : Indicate if hw rate limiting is used. (default=FALSE)\n"
   1894 "  PktsPerChain=<value> : Specify number of packets per DMA chain. (default=16)\n"
   1895 "  Chains=<value>       : Specify number of chains (DVs) set up.. (default=4)\n"
   1896 "  useINTR=<value>      : Indicate if packets are received in interrupt context. (default=TRUE)\n"
   1897 "  DumpRX=<value>       : Indicate if to show packet rx setting information. (default=FALSE)\n"
   1898 "  RxMode=<value>       : Indicate if rx mode is set via flags (parse received packets). (default=FALSE)\n"
   1899 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1900 "  SOCKet=<value>       : Indicate if socket is used for packet rx. (default=FALSE)\n"
   1901 "  RingBuf=<value>      : Specify ring buffer size for socket. (default=0)\n"
   1902 "  SocketTx=<value>     : Indicate if socket is used for packet tx. (default=FALSE)\n"
   1903 #endif
   1904 #endif
   1905 ;
   1906 
   1907 /*
   1908  * Function:
   1909  *      rpacket_init
   1910  * Purpose:
   1911  *      Initialize the rpacket test.
   1912  * Parameters:
   1913  *      u - unit #
   1914  *      a - pointer to args
   1915  *      pa - Pointer to cookie
   1916  * Returns:
   1917  *      0 - success, -1 - failed.
   1918  */
   1919 
   1920 int
   1921 rpacket_init(int u, args_t *a, void **pa)
   1922 {
   1923     p_t                 *p = p_control[u];
   1924     parse_table_t       pt;
   1925 
   1926 
   1927     if (p == NULL) {
   1928         p = sal_alloc(sizeof(p_t), "rpacket");
   1929         if (p == NULL) {
   1930             test_error(u, "ERROR: cannot allocate memory\n");
   1931             return -1;
   1932         }
   1933         sal_memset(p, 0, sizeof(p_t));
   1934         p_control[u] = p;
   1935     }
   1936 
   1937     if (!p->p_init) {                   /* Init defaults first time */
   1938         p->hdr_chk = 0;
   1939         p->diff_len = 4;
   1940         p->diff_len_chk = 1;
   1941         p->p_l_start = 64;
   1942         p->p_l_end = 1522;
   1943         p->p_l_inc = 64;
   1944         p->p_time  = 2;
   1945 
   1946         p->p_pkts_per_sec = 0;
   1947         p->p_max_q_len = -1;
   1948         p->p_per_cos = FALSE;
   1949         p->p_burst = 100;
   1950         p->p_hw_rate = FALSE;
   1951 
   1952         p->p_intr_cb = TRUE;
   1953         p->p_dump_rx = FALSE;
   1954         p->p_count_packets = FALSE;
   1955 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   1956         if (SOC_KNET_MODE(u)) {
   1957             p->p_use_socket = FALSE;
   1958             p->p_use_socket_send = FALSE;
   1959         }
   1960 #endif
   1961         /* Init the RX cfg here.  Not much exposed */
   1962        p->p_rx_cfg.pkt_size = 8 * 1024;
   1963 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT)
   1964        p->p_rx_cfg.pkts_per_chain = 16; 
   1965 #endif /* BCM_ESW_SUPPORT */
   1966 #ifdef BCM_FE2000_SUPPORT
   1967        p->p_rx_cfg.pkts_per_chain = 16;
   1968 #endif /* BCM_FE2000_SUPPORT */
   1969        p->p_rx_cfg.global_pps = p->p_pkts_per_sec;
   1970        p->p_rx_cfg.max_burst = p->p_burst;
   1971        p->p_rx_cfg.chan_cfg[1].chains = 4;
   1972        p->p_rx_cfg.chan_cfg[1].flags = 0;
   1973        p->p_rx_cfg.chan_cfg[1].cos_bmp = 0xff;
   1974        p->rx_mode = 0;
   1975        /* Not initializing alloc/free functions */
   1976         p->p_init  = TRUE;
   1977     }
   1978 
   1979     parse_table_init(u, &pt);
   1980     parse_table_add(&pt, "Time", PQ_DFL|PQ_INT, 0, &p->p_time, 0);
   1981     parse_table_add(&pt, "LengthStart", PQ_DFL|PQ_INT, 0, &p->p_l_start, 0);
   1982     parse_table_add(&pt, "LengthEnd", PQ_DFL|PQ_INT, 0, &p->p_l_end, 0);
   1983     parse_table_add(&pt, "LengthInc", PQ_DFL|PQ_INT, 0, &p->p_l_inc, 0);
   1984     parse_table_add(&pt, "FreeBuffer", PQ_DFL|PQ_BOOL, 0, &p->p_free_buffer,
   1985                     0);
   1986 
   1987     parse_table_add(&pt, "QLen", PQ_DFL|PQ_INT, 0, &p->p_max_q_len, 0);
   1988     parse_table_add(&pt, "PERCos", PQ_DFL|PQ_INT, 0, &p->p_per_cos, 0);
   1989     parse_table_add(&pt, "Rate", PQ_DFL|PQ_INT, 0, &p->p_pkts_per_sec, 0);
   1990     parse_table_add(&pt, "Burst", PQ_DFL|PQ_INT, 0, &p->p_burst, 0);
   1991     parse_table_add(&pt, "HWrate", PQ_DFL|PQ_INT, 0, &p->p_hw_rate, 0);
   1992     
   1993     parse_table_add(&pt, "PktsPerChain", PQ_DFL|PQ_INT, 0,
   1994                     &p->p_rx_cfg.pkts_per_chain, 0);
   1995 
   1996     parse_table_add(&pt, "Chains", PQ_DFL|PQ_INT, 0,
   1997                     &p->p_rx_cfg.chan_cfg[1].chains, 0);
   1998     parse_table_add(&pt, "useINTR", PQ_DFL|PQ_BOOL, 0, &p->p_intr_cb, 0);
   1999     parse_table_add(&pt, "DumpRX", PQ_DFL|PQ_BOOL, 0, &p->p_dump_rx, 0);
   2000     parse_table_add(&pt, "RxMode", PQ_DFL|PQ_INT, 0, &p->rx_mode, 0);
   2001 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   2002     parse_table_add(&pt, "SOCKet", PQ_DFL|PQ_INT, 0, &p->p_use_socket, 0);
   2003     parse_table_add(&pt, "RingBuf", PQ_DFL|PQ_INT, 0, &p->p_ringbuf_size, 0);
   2004     parse_table_add(&pt, "SocketTx", PQ_DFL|PQ_INT, 0, &p->p_use_socket_send, 0);
   2005 #endif  
   2006     
   2007     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   2008         test_error(u, "%s: Invalid option: %s\n",
   2009                    ARG_CMD(a), ARG_CUR(a) ? ARG_CUR(a) : "*");
   2010         cli_out("%s\n", rpacket_usage);
   2011         parse_arg_eq_done(&pt);
   2012         return -1;
   2013     }
   2014     parse_arg_eq_done(&pt);
   2015 
   2016     if (p->p_time < 1) {
   2017         test_error(u, "%s: Invalid duration: %d (must be 1 <= time)\n",
   2018                    ARG_CMD(a), p->p_time);
   2019         return -1;
   2020     }
   2021     
   2022     if (p->p_per_cos) {
   2023         p->p_hw_rate = 1;
   2024     }
   2025     
   2026     if (p->p_rx_cfg.pkts_per_chain > RP_MAX_PPC) {
   2027         cli_out("Too many pkts/chain (%d).  Setting to max (%d)\n",
   2028                 p->p_rx_cfg.pkts_per_chain, RP_MAX_PPC);
   2029         p->p_rx_cfg.pkts_per_chain = RP_MAX_PPC;
   2030     }
   2031     if (p->rx_mode) {
   2032         p->p_rx_cfg.flags |= BCM_RX_F_PKT_UNPARSED; 
   2033     }
   2034 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__))) 
   2035     if (SOC_KNET_MODE(u)) {
   2036         if (!p->p_use_socket) {
   2037             p->p_ringbuf_size = 0;
   2038         }
   2039         p->p_ringbuf = NULL;
   2040         if (p->p_ringbuf_size > MAX_RXRING_FRAMES) {
   2041             p->p_ringbuf_size = MAX_RXRING_FRAMES;
   2042         }
   2043         if (p->p_ringbuf_size > 0) {
   2044             p->p_use_socket = TRUE;  /* ringbuf implies raw socket */
   2045         } else {
   2046             p->p_ringbuf_size = 0;
   2047         }
   2048     } else {
   2049         if (p->p_use_socket) {
   2050             cli_out("KNET not online, please insert the kernel module firstly.\n");
   2051             return -1;
   2052         }
   2053     }
   2054 #endif
   2055 
   2056 #ifdef BCM_DNX_SUPPORT
   2057     if (SOC_IS_DNX(u))
   2058     {
   2059         if (soc_feature(u, soc_feature_no_ep_to_cpu))
   2060         {
   2061             /** Set to 1 to avoid to check length of EP_TO_CPU header on DNX */
   2062             p->hdr_chk = 1;
   2063         }
   2064         p->diff_len += DNX_MODULE_HEADER_SIZE;
   2065         p->diff_len += 2;
   2066         /** Bypass length check */
   2067         p->diff_len_chk = 0;
   2068     }
   2069 
   2070 #endif
   2071 #ifdef BCM_PETRA_SUPPORT
   2072     if (SOC_IS_ARAD(u))
   2073     {
   2074         /** Set to 1 to avoid to check length of EP_TO_CPU header on DNX */
   2075         p->hdr_chk = 1;
   2076         p->diff_len += 2;
   2077     }
   2078 #endif
   2079 
   2080     if (rpacket_setup(u, p) < 0) {
   2081         (void)rpacket_done(u, p);
   2082         return -1;
   2083     }
   2084 
   2085     *pa = (void *)p;
   2086 
   2087 
   2088 #if (defined(INCLUDE_KNET) && defined(LINUX) && (!defined(__KERNEL__)))
   2089     if (SOC_KNET_MODE(u)) {
   2090         (void)knetif_setup(u, p);
   2091     }
   2092 #endif
   2093     return 0;
   2094 }
   2095 
   2096 #endif /* BCM_FIELD_SUPPORT || BCM_FE2000_SUPPORT || BCM_PETRA_SUPPORT || BCM_DNX_SUPPORT */