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

streaming_ipmc.c (46238B)


      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  * Streaming test to check TDM table and programming. Each port loops traffic
      8  * back to itself using port bridging and higig lookup for HG ports. Test test
      9  * calculates expected rates based on port config and oversub ratio and checks
     10  * against it.
     11  * Configuration parameters passed from CLI:
     12  * PktSize: Packet size in bytes. Set to 0 for worst case packet sizes on all
     13  *          ports (145B for ENET, 76B for HG2). Set to 1 for random packet sizes
     14  * FloodCnt: Number of packets in each swill. Setting this to 0 will let the
     15  *           test calculate the number of packets that can be sent to achieve
     16  *           a lossless swirl at full rate. Set to 0 by default.
     17  * Setup and Test Sequence:
     18  * 1. Group all active front panel ports into groups of
     19  *    (NumL2Copy + NumL3Copy+ 1) ports. Each group constitutes 1 IPMC "stream".
     20  *    All ports in a stream should have the same line rate, although they may
     21  *    have different oversub ratios.
     22  * 2. Let us assume a stream has n ports P0, P1 ... Pn. The ports should be
     23  *    arranged such that the P1 is the slowest port, i.e. has the highest oversub
     24  *    ratio and the highest number of same port replications.
     25  * 3. Turn off all flow control, set MAC loopback on all ports and disable TTL
     26  *    decrement by setting EGR_IPMC_CFG2.DISABLE_TTL_DECREMENT=1.
     27  * 4. Randomly decide whether each receiving port in the stream (P1, P2, ... Pn)
     28  *    should receive L2 or L3 copies. If port P1 receives L2 copies, the IPMC
     29  *    stream is designated an "L2 stream". If it receives L3 copies the stream
     30  *    is designated an "L3 stream".
     31  * 5. For each stream:
     32  *      a. Place port P0 on VLAN0. Create an empty VLAN called DROP_VLAN with
     33  *         no ports
     34  *      b. Add all ports receiving L2 copies to VLAN1 and multicast group MC0
     35  *         using bcm_multicast_egress_add(). This programs the L2MC table.
     36  *      c. Add the following VLAN translations:
     37  *          i. For L2 streams: Port=P2, P3 ... Pn OldVlan=VLAN1 NewVlan=DROP_VLAN
     38  *          ii. For L3 streams: Port=P1, P2 ... Pn OldVlan=VLAN1 NewVlan=DROP_VLAN
     39  *          iii. Port=P0 OldVlan=VLAN0 NewVlan=VLAN1
     40  *          iv. For L2 streams: Port=P1 OldVlan=VLAN1 NewVlan=DROP_VLAN
     41  *      d. For each port Pk receiving L3 copies, let the number of L3 copies received at a port be m (=NumRep+1).
     42  *          i. Create m VLANs (VLANk0, VLANk1, .... VLANk(m-1)), each with port Pk
     43  *          ii. For L3 streams: If k=1, VLAN2=VLANk0
     44  *          iii. For L3 streams: Create the following VLAN translation: Port=Pk OldVlan=VLAN2 NewVlan=VLAN0
     45  *          iv. For L2 streams: Create the following VLAN translation: Port=Pk OldVlan= VLANk0, VLANk1, ... VLANk(m-1)) NewVlan=DROP_VLAN
     46  *          v. Create m L3 interfaces I0, I1 ... I(m-1) with VLANk0, VLANk1, .... VLANk(m-1)
     47  *          vi. Add interface to multicat group MC1 using bcm_multicast_egress_add().
     48  *          vii. Program IPMC table with necessary SIP, DIP and multicast group MC1.
     49  * 6. Send packets from CPU port on VLAN0 of each stream to flood the stream.
     50  *    If FloodCnt=0, the test will determine the number of packets to send based.
     51  *    These values are obtained empirically through trial and error for LR ports
     52  *    for NumCopy=2 and adjusted for oversub configs based on oversub ratio.
     53  *    Embed the packet size and random seed used to generate each packet in the
     54  *    payload.
     55  * 7. Allow the packets to swill for a fixed amount of time decided by RunTime.
     56  * 8. Snoop back all packets in each stream to the CPU using the following sequence:
     57  *      a. Program CPU_CONTROL_0.UVLAN_TOCPU=1. This sends all packets with an unknown VLAN to CPU.
     58  *      b. Invalidate VLAN0 for all streams by setting VALID=0 in the VLAN table
     59  * 9. Decode each received packet to obtain the random seed and packet size.
     60  *    Reconstruct the expected packet and check the received packet for integrity.
     61  * Checks:
     62  * 1. Packet counts on each port.
     63  * 2. No packet drops on any stream for LR configs.
     64  * 3. All packets in a given stream snooped back to CPU port and checked for integrity.
     65  * 
     66  * Test Limitations
     67  * 1. FloodCnt automatically computed in the test supports packet sizes upto
     68  *    1518B and NumCopy=2. Any deviations may result in packet drops for LR
     69  *    configs or false rate errors being reported. For custom configs the user is
     70  *    encouraged to tweak the FloodCnt value as per their needs.
     71  *
     72  * PktSize : Packet size in bytes not including HG2 header. Set to 0 for worst
     73  *           case packet sizes (145B for Ethernet and 76B for HG2). Set to 1 for
     74  *           random packet sizes.
     75  * FloodCnt: Number of packets sent from CPU to flood each stream (packet swill).
     76  *           Set to 0 for test to automatically calculate.
     77  * NumL2Copy: Number of ports receiving L2 copies in each stream (2 by default).
     78  * NumL3Copy:  Number of ports receiving L3 copies in each stream (2 by default).
     79  * NumRep: Number of same-port replications on ports receiving . Set to 0 for
     80  *         random.
     81  * MaxNumRep: Max number of replications if NumRep=0. Set both MaxNumRep and
     82  *            NumRep to 0 for no same port replication.
     83  * MaxNumCells: Max number of cells for random packet sizes. Default = 4.
     84  *              Set to 0 for random.
     85  * RunTime: Interval in seconds over which swill is allowed to
     86  *          run (10s by default).
     87  */
     88 
     89 #include <appl/diag/system.h>
     90 #include <shared/alloc.h>
     91 #include <shared/bsl.h>
     92 
     93 #include <soc/cm.h>
     94 #include <soc/dma.h>
     95 #include <soc/drv.h>
     96 #include <soc/dcb.h>
     97 #include <soc/cmicm.h>
     98 #include <soc/cmic.h>
     99 
    100 #include <sal/types.h>
    101 #include <appl/diag/parse.h>
    102 #include <bcm/port.h>
    103 #include <bcm/vlan.h>
    104 #include <bcm/link.h>
    105 #include <bcm/ipmc.h>
    106 #include <bcm/multicast.h>
    107 
    108 #include "testlist.h"
    109 #include "gen_pkt.h"
    110 #include "streaming_lib.h"
    111 
    112 #define MAC_DA {0x01,0x00,0x5e,0x02,0x03,0x04}
    113 #define MAC_SA {0x00,0x00,0x00,0x00,0x00,0x01}
    114 #define VLAN 0x2
    115 
    116 #define TARGET_PKT_COUNT 100
    117 #define MAX_FP_PORTS 130
    118 
    119 #define TTL 5
    120 
    121 #define DROP_VLAN 0xabc
    122 #define FIRST_MC_GROUP 0x2000001
    123 #define FIRST_INTF_ID 0x2
    124 
    125 #define SIP 0x02030405
    126 #define DIP 0xe0020304
    127 
    128 #define MAX_PKTS_PER_STREAM 30
    129 #define PKT_COUNT_CHECK_TOL 5
    130 
    131 #define PKT_SIZE_PARAM_DEFAULT 0
    132 #define FLOOD_PKT_CNT_PARAM_DEFAULT 0
    133 #define NUM_L2_COPY_PARAM_DEFAULT 2
    134 #define NUM_L3_COPY_PARAM_DEFAULT 2
    135 #define NUM_REP_PARAM_DEFAULT 1
    136 #define MAX_NUM_REP_PARAM_DEFAULT 3
    137 #define RUN_TIME_PARAM_DEFAULT 10
    138 #define MAX_NUM_CELLS_PARAM_DEFAULT 4
    139 #define SPEEDUP_FACTOR_PARAM_DEFAULT 1
    140 #define CPU_PORT 0
    141 
    142 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_L3) && \
    143       (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT))
    144 
    145 typedef struct ipmc_s {
    146     uint32 num_fp_ports;
    147     uint32 num_streams;
    148     int *port_speed;
    149     int *port_list;
    150     int **stream;
    151     uint32 *num_rep;
    152     uint32 *l3_copy;
    153     uint32 *tx_vlan;
    154     uint32 *exp_vlan;
    155     uint8 (*exp_mac_addr)[NUM_BYTES_MAC_ADDR];
    156     uint32 *port_oversub;
    157     uint32 oversub_config;
    158     uint32 *port_used;
    159     uint32 num_pipes;
    160     uint32 total_chip_bw;
    161     uint32 bw_per_pipe;
    162     uint32 *ovs_ratio_x1000;
    163     uint64 *exp_rate;
    164     uint64 *tpkt_start;
    165     uint64 *tpkt_end;
    166     uint32 **rand_pkt_sizes;
    167     uint32 pkt_size_param;
    168     uint32 flood_pkt_cnt_param;
    169     uint32 num_l2_copy_param;
    170     uint32 num_l3_copy_param;
    171     uint32 check_packet_integrity_param;
    172     uint32 num_rep_param;
    173     uint32 max_num_rep_param;
    174     uint32 max_num_cells_param;
    175     uint32 run_time_param;
    176     uint32 scaling_factor_param;
    177     uint32 bad_input;
    178     int test_fail;
    179     uint32 pkt_seed;
    180     uint32 num_copy;
    181 } ipmc_t;
    182 
    183 static ipmc_t *ipmc_parray[SOC_MAX_NUM_DEVICES];
    184 
    185 /*
    186  * Function:
    187  *      ipmc_parse_test_params
    188  * Purpose:
    189  *      Parse CLI parameters, create test structure and flag bad inputs.
    190  * Parameters:
    191  *      unit - StrataSwitch Unit #.
    192  *      a - Pointer to arguments
    193  *
    194  * Returns:
    195  *     Nothing
    196  * Notes:
    197  *      ipmc_p->bad_input set from here - tells test to crash out in case
    198  *      CLI input combination is invalid.
    199  */
    200 static void
    201 ipmc_parse_test_params(int unit, args_t *a)
    202 {
    203     parse_table_t parse_table;
    204     ipmc_t *ipmc_p = ipmc_parray[unit];
    205 
    206     const char tr513_test_usage[] =
    207 #ifdef COMPILER_STRING_CONST_LIMIT
    208     "\nDocumentation too long to be displayed with -pedantic compiler\n";
    209 #else
    210     "Streaming test to check TDM table and programming. Each port loops traffic\n"
    211     "back to itself using port bridging and higig lookup for HG ports. Test test\n"
    212     "calculates expected rates based on port config and oversub ratio and checks\n"
    213     "against it.\n"
    214     "Configuration parameters passed from CLI:\n"
    215     "PktSize: Packet size in bytes. Set to 0 for worst case packet sizes on all\n"
    216     "        ports (145B for ENET, 76B for HG2). Set to 1 for random packet sizes\n"
    217     "FloodCnt: Number of packets in each swill. Setting this to 0 will let the\n"
    218     "        test calculate the number of packets that can be sent to achieve\n"
    219     "        a lossless swirl at full rate. Set to 0 by default.\n"
    220     "Setup and Test Sequence:\n"
    221     "1. Group all active front panel ports into groups of\n"
    222     "    (NumL2Copy + NumL3Copy+ 1) ports. Each group constitutes 1 IPMC \"stream\".\n"
    223     "    All ports in a stream should have the same line rate, although they may\n"
    224     "    have different oversub ratios.\n"
    225     "2. Let us assume a stream has n ports P0, P1 ... Pn. The ports should be\n"
    226     "    arranged such that the P1 is the slowest port, i.e. has the highest oversub\n"
    227     "    ratio and the highest number of same port replications.\n"
    228     "3. Turn off all flow control, set MAC loopback on all ports and disable TTL\n"
    229     "    decrement by setting EGR_IPMC_CFG2.DISABLE_TTL_DECREMENT=1.\n"
    230     "4. Randomly decide whether each receiving port in the stream (P1, P2, ... Pn)\n"
    231     "    should receive L2 or L3 copies. If port P1 receives L2 copies, the IPMC\n"
    232     "    stream is designated an \"L2 stream\". If it receives L3 copies the stream\n"
    233     "    is designated an \"L3 stream\".\n"
    234     "5. For each stream:\n"
    235     "    a. Place port P0 on VLAN0. Create an empty VLAN called DROP_VLAN with\n"
    236     "        no ports\n"
    237     "    b. Add all ports receiving L2 copies to VLAN1 and multicast group MC0\n"
    238     "        using bcm_multicast_egress_add(). This programs the L2MC table.\n"
    239     "    c. Add the following VLAN translations:\n"
    240     "        i. For L2 streams: Port=P2, P3 ... Pn OldVlan=VLAN1 NewVlan=DROP_VLAN\n"
    241     "        ii. For L3 streams: Port=P1, P2 ... Pn OldVlan=VLAN1 NewVlan=DROP_VLAN\n"
    242     "        iii. Port=P0 OldVlan=VLAN0 NewVlan=VLAN1\n"
    243     "        iv. For L2 streams: Port=P1 OldVlan=VLAN1 NewVlan=DROP_VLAN\n"
    244     "    d. For each port Pk receiving L3 copies, let the number of L3 copies received at a port be m (=NumRep+1).\n"
    245     "        i. Create m VLANs (VLANk0, VLANk1, .... VLANk(m-1)), each with port Pk\n"
    246     "        ii. For L3 streams: If k=1, VLAN2=VLANk0\n"
    247     "        iii. For L3 streams: Create the following VLAN translation: Port=Pk OldVlan=VLAN2 NewVlan=VLAN0\n"
    248     "        iv. For L2 streams: Create the following VLAN translation: Port=Pk OldVlan= VLANk0, VLANk1, ... VLANk(m-1)) NewVlan=DROP_VLAN\n"
    249     "        v. Create m L3 interfaces I0, I1 ... I(m-1) with VLANk0, VLANk1, .... VLANk(m-1)\n"
    250     "        vi. Add interface to multicat group MC1 using bcm_multicast_egress_add().\n"
    251     "        vii. Program IPMC table with necessary SIP, DIP and multicast group MC1.\n"
    252     "6. Send packets from CPU port on VLAN0 of each stream to flood the stream.\n"
    253     "    If FloodCnt=0, the test will determine the number of packets to send based.\n"
    254     "    These values are obtained empirically through trial and error for LR ports\n"
    255     "    for NumCopy=2 and adjusted for oversub configs based on oversub ratio.\n"
    256     "    Embed the packet size and random seed used to generate each packet in the\n"
    257     "    payload.\n"
    258     "7. Allow the packets to swill for a fixed amount of time decided by RunTime.\n"
    259     "8. Snoop back all packets in each stream to the CPU using the following sequence:\n"
    260     "    a. Program CPU_CONTROL_0.UVLAN_TOCPU=1. This sends all packets with an unknown VLAN to CPU.\n"
    261     "    b. Invalidate VLAN0 for all streams by setting VALID=0 in the VLAN table\n"
    262     "9. Decode each received packet to obtain the random seed and packet size.\n"
    263     "    Reconstruct the expected packet and check the received packet for integrity.\n"
    264     "Checks:\n"
    265     "1. Packet counts on each port.\n"
    266     "2. No packet drops on any stream for LR configs.\n"
    267     "3. All packets in a given stream snooped back to CPU port and checked for integrity.\n"
    268     "\n"
    269     " Test Limitations\n"
    270     " 1. FloodCnt automatically computed in the test supports packet sizes upto\n"
    271     "    1518B and NumCopy=2. Any deviations may result in packet drops for LR\n"
    272     "    configs or false rate errors being reported. For custom configs the user is\n"
    273     "    encouraged to tweak the FloodCnt value as per their needs.\n"
    274     "\n"
    275     " PktSize : Packet size in bytes not including HG2 header. Set to 0 for worst\n"
    276     "           case packet sizes (145B for Ethernet and 76B for HG2). Set to 1 for\n"
    277     "           random packet sizes.\n"
    278     " FloodCnt: Number of packets sent from CPU to flood each stream (packet swill).\n"
    279     "           Set to 0 for test to automatically calculate.\n"
    280     " NumL2Copy: Number of ports receiving L2 copies in each stream (2 by default).\n"
    281     " NumL3Copy:  Number of ports receiving L3 copies in each stream (2 by default).\n"
    282     " NumRep: Number of same-port replications on ports receiving . Set to 0 for\n"
    283     "         random.\n"
    284     " MaxNumRep: Max number of replications if NumRep=0. Set both MaxNumRep and\n"
    285     "            NumRep to 0 for no same port replication.\n"
    286     " MaxNumCells: Max number of cells for random packet sizes. Default = 4.\n"
    287     "              Set to 0 for random.\n"
    288     " RunTime: Interval in seconds over which swill is allowed to\n"
    289     "          run (10s by default).\n";
    290 #endif
    291     ipmc_p->bad_input = 0;
    292 
    293     ipmc_p->pkt_size_param = PKT_SIZE_PARAM_DEFAULT;
    294     ipmc_p->flood_pkt_cnt_param = FLOOD_PKT_CNT_PARAM_DEFAULT;
    295     ipmc_p->num_l2_copy_param = NUM_L2_COPY_PARAM_DEFAULT;
    296     ipmc_p->num_l3_copy_param = NUM_L3_COPY_PARAM_DEFAULT;
    297     ipmc_p->num_rep_param = NUM_REP_PARAM_DEFAULT;
    298     ipmc_p->max_num_rep_param = MAX_NUM_REP_PARAM_DEFAULT;
    299     ipmc_p->max_num_cells_param = MAX_NUM_CELLS_PARAM_DEFAULT;
    300     ipmc_p->run_time_param = RUN_TIME_PARAM_DEFAULT;
    301     ipmc_p->scaling_factor_param = SPEEDUP_FACTOR_PARAM_DEFAULT;
    302 
    303     /*Parse CLI opts */
    304 
    305     parse_table_init(unit, &parse_table);
    306     parse_table_add(&parse_table, "PktSize", PQ_INT|PQ_DFL, 0,
    307                     &(ipmc_p->pkt_size_param), NULL);
    308     parse_table_add(&parse_table, "FloodCnt", PQ_INT|PQ_DFL, 0,
    309                     &(ipmc_p->flood_pkt_cnt_param), NULL);
    310     parse_table_add(&parse_table, "NumL2Copy", PQ_INT|PQ_DFL, 0,
    311                     &(ipmc_p->num_l2_copy_param), NULL);
    312     parse_table_add(&parse_table, "NumL3Copy", PQ_INT|PQ_DFL, 0,
    313                     &(ipmc_p->num_l3_copy_param), NULL);
    314     parse_table_add(&parse_table, "NumRep", PQ_INT|PQ_DFL, 0,
    315                     &(ipmc_p->num_rep_param), NULL);
    316     parse_table_add(&parse_table, "MaxNumRep", PQ_INT|PQ_DFL, 0,
    317                     &(ipmc_p->max_num_rep_param), NULL);
    318     parse_table_add(&parse_table, "MaxNumCells", PQ_INT|PQ_DFL, 0,
    319                     &(ipmc_p->max_num_cells_param), NULL);
    320     parse_table_add(&parse_table, "RunTime", PQ_INT|PQ_DFL, 0,
    321                     &(ipmc_p->run_time_param), NULL);
    322     parse_table_add(&parse_table, "ScalingFactor", PQ_INT|PQ_DFL, 0,
    323                     &(ipmc_p->scaling_factor_param), NULL);
    324 
    325     if (parse_arg_eq(a, &parse_table) < 0 || ARG_CNT(a) != 0) {
    326         test_msg("%s", tr513_test_usage);
    327         test_error(unit,
    328                    "%s: Invalid option: %s\n",
    329                    ARG_CMD(a),
    330                    ARG_CUR(a) ? ARG_CUR(a) : "*");
    331         ipmc_p->bad_input = 1;
    332         parse_arg_eq_done(&parse_table);
    333     } else {
    334         cli_out("\n");
    335         cli_out("------------- PRINTING TEST PARAMS ------------------\n");
    336         cli_out("PktSize      = %0d\n", ipmc_p->pkt_size_param);
    337         cli_out("FloodCnt     = %0d\n", ipmc_p->flood_pkt_cnt_param);
    338         cli_out("NumL2Copy    = %0d\n", ipmc_p->num_l2_copy_param);
    339         cli_out("NumL3Copy    = %0d\n", ipmc_p->num_l3_copy_param);
    340         cli_out("NumRep       = %0d\n", ipmc_p->num_rep_param);
    341         cli_out("MaxNumRep    = %0d\n", ipmc_p->max_num_rep_param);
    342         cli_out("MaxNumCells  = %0d\n", ipmc_p->max_num_cells_param);
    343         cli_out("RunTime      = %0d\n", ipmc_p->run_time_param);
    344         cli_out("ScalingFactor= %0d\n", ipmc_p->scaling_factor_param);
    345         cli_out("-----------------------------------------------------\n");
    346     }
    347 
    348     if (ipmc_p->max_num_cells_param == 0) {
    349         /* coverity[dont_call : FALSE] */
    350         ipmc_p->max_num_cells_param = (sal_rand() % (MTU_CELL_CNT - 1)) + 1;
    351     }
    352 
    353     if (ipmc_p->pkt_size_param == 0) {
    354         cli_out
    355             ("\nUsing worst case packet sizes - 145B for Ethernet "
    356              "and 76B (64B + 12B hg-hdr) for HG2");
    357     } else if (ipmc_p->pkt_size_param == 1) {
    358         cli_out("\nUsing random packet sizes");
    359     } else if (ipmc_p->pkt_size_param < MIN_PKT_SIZE) {
    360         test_error(unit,"\n*ERROR: Packet size cannot be lower than %0dB\n",
    361                 MIN_PKT_SIZE);
    362         ipmc_p->bad_input = 1;
    363     } else if (ipmc_p->pkt_size_param > MTU) {
    364         test_error(unit,"\n*ERROR: Packet size cannot be higher than %0dB (Device MTU)\n",
    365                 MTU);
    366         ipmc_p->bad_input = 1;
    367     }
    368 
    369     if (ipmc_p->flood_pkt_cnt_param == 0) {
    370         cli_out("\nFloodCnt=0, test will automatically calculate number of"
    371                 " packets to flood each port");
    372     }
    373 
    374     if (ipmc_p->num_rep_param > MAX_NUM_REP_PARAM_DEFAULT) {
    375         ipmc_p->max_num_rep_param = MAX_NUM_REP_PARAM_DEFAULT;
    376         cli_out("\nMax replications supported by this test = %0d,"
    377                 "forcing number of replications to %0d",
    378                 MAX_NUM_REP_PARAM_DEFAULT, MAX_NUM_REP_PARAM_DEFAULT);
    379     }
    380 
    381     ipmc_p->num_copy = ipmc_p->num_l2_copy_param + ipmc_p->num_l3_copy_param;
    382 }
    383 
    384 /*
    385  * Function:
    386  *      ipmc_set_lowest_stream_port
    387  * Purpose:
    388  *      Within each stream, put the port with the lowest speed
    389  *      in the 2nd position.
    390  * Parameters:
    391  *      unit: StrataSwitch Unit #.
    392  *
    393  * Returns:
    394  *     Nothing
    395  */
    396 static void
    397 ipmc_set_lowest_stream_port(int unit)
    398 {
    399     int i, j, tmp, port, port_speed, min_speed, min_speed_idx;
    400     ipmc_t *ipmc_p = ipmc_parray[unit];
    401 
    402     for (i = 0; i < ipmc_p->num_streams; i++) {
    403         min_speed_idx = 1;
    404         port = ipmc_p->port_list[ipmc_p->stream[i][min_speed_idx]];
    405         bcm_port_speed_get(unit, port, &min_speed);
    406 
    407         for (j = 0; j < (ipmc_p->num_copy + 1); j++) {
    408             port = ipmc_p->port_list[ipmc_p->stream[i][j]];
    409             bcm_port_speed_get(unit, port, &port_speed);
    410             if (port_speed < min_speed) {
    411                 min_speed = port_speed;
    412                 min_speed_idx = j;
    413             }
    414         }
    415         if (min_speed_idx != 1) {
    416             tmp = ipmc_p->stream[i][1];
    417             ipmc_p->stream[i][1] =  ipmc_p->stream[i][min_speed_idx];
    418             ipmc_p->stream[i][min_speed_idx] = tmp;
    419         }
    420     }
    421 }
    422 
    423 /*
    424  * Function:
    425  *      ipmc_set_port_property
    426  * Purpose:
    427  *      Set port_list, port_speed, port_oversub arrays and l3_copy.
    428  *      Also call set_exp_rates.
    429  * Parameters:
    430  *      unit: StrataSwitch Unit #.
    431  *
    432  * Returns:
    433  *     Nothing.
    434  */
    435 static void
    436 ipmc_set_port_property(int unit)
    437 {
    438     int i, j, k, p, picked_port;
    439     uint32 temp, pkt_size, ports_found = 0, ports_picked = 0,
    440            ports_accounted_for = 0, stream_possible = 0;
    441     soc_info_t *si = &SOC_INFO(unit);
    442     ipmc_t *ipmc_p = ipmc_parray[unit];
    443 
    444     ipmc_p->num_fp_ports = 0;
    445     ipmc_p->num_streams = 0;
    446     ipmc_p->oversub_config = 0;
    447 
    448     PBMP_ITER(PBMP_PORT_ALL(unit), p) {
    449         ipmc_p->num_fp_ports++;
    450     }
    451 
    452     ipmc_p->port_list =
    453         (int *)sal_alloc(ipmc_p->num_fp_ports * sizeof(int),
    454                          "port_list");
    455     ipmc_p->port_speed =
    456         (int *)sal_alloc(ipmc_p->num_fp_ports * sizeof(int),
    457                          "port_speed_array");
    458     ipmc_p->port_oversub =
    459         (uint32 *) sal_alloc(ipmc_p->num_fp_ports * sizeof(uint32),
    460                              "port_oversub_array");
    461 
    462     ipmc_p->l3_copy =
    463         (uint32 *) sal_alloc(ipmc_p->num_fp_ports * sizeof(uint32),
    464                              "l3_copy");
    465     ipmc_p->rand_pkt_sizes =
    466         (uint32 **) sal_alloc(ipmc_p->num_fp_ports * sizeof(uint32 *),
    467                               "rand_pkt_sizes_array*");
    468 
    469     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    470         ipmc_p->rand_pkt_sizes[i] =
    471             (uint32 *) sal_alloc(TARGET_PKT_COUNT * sizeof(uint32),
    472                                 "rand_pkt_sizes_array");
    473     }
    474 
    475     ipmc_p->num_rep =
    476         (uint32 *) sal_alloc(ipmc_p->num_fp_ports * sizeof(uint32),
    477                               "num_rep_array");
    478 
    479     ipmc_p->stream =
    480         (int **) sal_alloc(ipmc_p->num_fp_ports * sizeof(int *),
    481                               "stream_array*");
    482 
    483     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    484         ipmc_p->stream[i] =
    485             (int *) sal_alloc((ipmc_p->num_copy + 1) * sizeof(int),
    486                                 "stream_array");
    487     }
    488     ipmc_p->port_used =
    489         (uint32 *) sal_alloc(ipmc_p->num_fp_ports * sizeof(uint32),
    490                              "ipmc_p->port_used_array");
    491 
    492     i = 0;
    493     PBMP_ITER(PBMP_PORT_ALL(unit), p) {
    494         ipmc_p->port_list[i] = p;
    495         i++;
    496     }
    497 
    498     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    499         ipmc_p->port_speed[i] =
    500             si->port_speed_max[ipmc_p->port_list[i]];
    501 
    502         switch(ipmc_p->port_speed[i]) {
    503             case 11000: ipmc_p->port_speed[i] = 10600; break;
    504             case 27000: ipmc_p->port_speed[i] = 26500; break;
    505             case 42000: ipmc_p->port_speed[i] = 42400; break;
    506             default: break;
    507         }
    508     }
    509 
    510     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    511         if (SOC_PBMP_MEMBER(si->oversub_pbm, ipmc_p->port_list[i]) &&
    512             (!(SOC_PBMP_MEMBER(si->management_pbm, ipmc_p->port_list[i])))) {
    513             ipmc_p->oversub_config = 1;
    514             ipmc_p->port_oversub[i] = 1;
    515         } else {
    516             ipmc_p->port_oversub[i] = 0;
    517         }
    518     }
    519 
    520     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    521         ipmc_p->port_used[i] = 0;
    522     }
    523 
    524     while (ports_accounted_for < ipmc_p->num_fp_ports) {
    525         do {
    526             i = sal_rand() % ipmc_p->num_fp_ports;
    527         }while (ipmc_p->port_used[i] != 0);
    528         stream_possible = 0;
    529         ports_found = 0;
    530         for (j = 0;j < ipmc_p->num_fp_ports; j++) {
    531             if((ipmc_p->port_used[j] == 0)
    532                     && (ipmc_p->port_speed[i]
    533                                 == ipmc_p->port_speed[j])
    534                     && (i!=j)) {
    535                 ports_found++;
    536             }
    537 
    538             if (ports_found >= ipmc_p->num_copy) {
    539                 stream_possible = 1;
    540             }
    541         }
    542 
    543         ports_accounted_for++;
    544         if(stream_possible == 1) {
    545             ipmc_p->port_used[i] = 1;
    546             ports_picked = 0;
    547             ipmc_p->stream[ipmc_p->num_streams][0] = i;
    548             while (ports_picked < ipmc_p->num_copy) {
    549                 do {
    550                     picked_port = sal_rand() % ipmc_p->num_fp_ports;
    551                 }while((ipmc_p->port_speed[i] !=
    552                                 ipmc_p->port_speed[picked_port])
    553                         || (ipmc_p->port_used[picked_port] != 0));
    554 
    555                 ports_picked++;
    556                 ipmc_p->port_used[picked_port] = 1;
    557                 ipmc_p->stream[ipmc_p->num_streams][ports_picked]
    558                                                             = picked_port;
    559                 ports_accounted_for++;
    560             }
    561             ipmc_p->num_streams++;
    562         }
    563     }
    564     ipmc_set_lowest_stream_port(unit);
    565 
    566     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    567         ipmc_p->l3_copy[i] = 0;
    568     }
    569     for (i = 0; i < ipmc_p->num_streams; i++) {
    570         for (j = 0; j < ipmc_p->num_l3_copy_param; j++) {
    571             do {
    572                 k = (sal_rand() % ipmc_p->num_copy) + 1;
    573             } while(ipmc_p->l3_copy[ipmc_p->stream[i][k]] == 1);
    574 
    575             ipmc_p->l3_copy[ipmc_p->stream[i][k]] = 1;
    576         }
    577     }
    578 
    579     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    580         if (ipmc_p->l3_copy[i] == 1) {
    581             if (ipmc_p->num_rep_param == 0) {
    582                 ipmc_p->num_rep[i] = sal_rand() %
    583                                      (ipmc_p->max_num_rep_param + 1);
    584             } else {
    585                 ipmc_p->num_rep[i] = ipmc_p->num_rep_param;
    586             }
    587         }
    588         else {
    589             ipmc_p->num_rep[i] = 0;
    590         }
    591     }
    592 
    593     for (i = 0; i < ipmc_p->num_streams; i++) {
    594         for (j = 0; j < (ipmc_p->num_copy + 1); j++) {
    595             if (ipmc_p->l3_copy[ipmc_p->stream[i][1]] == 0) {
    596                 ipmc_p->num_rep[ipmc_p->stream[i][j]] = 0;
    597             } else if (ipmc_p->num_rep[ipmc_p->stream[i][j]] >
    598                             ipmc_p->num_rep[ipmc_p->stream[i][1]]) {
    599                 temp = ipmc_p->num_rep[ipmc_p->stream[i][j]];
    600                 ipmc_p->num_rep[ipmc_p->stream[i][j]]
    601                                 = ipmc_p->num_rep[ipmc_p->stream[i][1]];
    602                 ipmc_p->num_rep[ipmc_p->stream[i][1]] = temp;
    603             }
    604         }
    605     }
    606 
    607     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
    608         for (j = 0; j < TARGET_PKT_COUNT; j++) {
    609             do {
    610                 /* coverity[dont_call : FALSE] */
    611                 pkt_size = (sal_rand() % (MTU - MIN_PKT_SIZE + 1)) + MIN_PKT_SIZE;
    612             } while (stream_get_pkt_cell_cnt(unit, pkt_size, ipmc_p->port_list[i]) >
    613                             ipmc_p->max_num_cells_param);
    614             ipmc_p->rand_pkt_sizes[i][j] = pkt_size;
    615         }
    616     }
    617 
    618     {
    619         /* print */
    620         int port_idx;
    621         cli_out("\n=========== STREAM INFO ============\n");
    622         cli_out("%4s %4s \t[%s]%4s %s/%s\n",
    623                 "strm", "type", "j", "port", "type", "num_l3cpy");
    624 
    625         for (i = 0; i < ipmc_p->num_streams; i++) {
    626             cli_out("%4d ", i);
    627             if (ipmc_p->l3_copy[ipmc_p->stream[i][1]] == 0) {
    628                 cli_out("%4s ", "L2");
    629             } else {
    630                 cli_out("%4s ", "L3");
    631             }
    632             for (j = 0; j < (ipmc_p->num_copy + 1); j++) {
    633                 port_idx = ipmc_p->stream[i][j];
    634                 cli_out("\t[%d]%4d ", j, ipmc_p->port_list[port_idx]);
    635                 if (ipmc_p->l3_copy[port_idx] == 0) {
    636                     cli_out("%s/%d", "L2", 0);
    637                 } else {
    638                     cli_out("%s/%d", "L3", (ipmc_p->num_rep[port_idx] + 1));
    639                 }
    640             }
    641             cli_out("\n");
    642         }
    643     }
    644 }
    645 
    646 /*
    647  * Function:
    648  *      ipmc_set_up_streams
    649  * Purpose:
    650  *      This function actually sets up the IPMC packet flow. Please refer to
    651  *      items 4-6 of the "Test Setup" section of the test description at the
    652  *      beginning of this file.
    653  * Parameters:
    654  *      unit: StrataSwitch Unit #.
    655  *
    656  * Returns:
    657  *     Nothing.
    658  */
    659 static void
    660 ipmc_set_up_streams(int unit)
    661 {
    662     int i, j, k, p;
    663     pbmp_t pbm, ubm;
    664     uint32 vlan = VLAN;
    665     uint32 vlan_0 = 0, vlan_1 = 0, vlan_2 = 0;
    666     uint32 l3_stream;
    667     bcm_multicast_t mc_group;
    668     uint32 mc_flags = 0;
    669     bcm_l3_intf_t l3_intf;
    670     bcm_if_t intf_id;
    671     bcm_if_t encap_id;
    672     uint32 intf_flags = 0;
    673     uint8 intf_mac[] = {0x00,0x00,0x00,0x00,0x00,0x00};
    674     uint8 mac_0[NUM_BYTES_MAC_ADDR];
    675     bcm_ipmc_addr_t ipmc_addr;
    676     uint32 ipmc_flags = 0;
    677     uint8 mac_sa[] = MAC_SA;
    678     bcm_gport_t gport;
    679     ipmc_t *ipmc_p = ipmc_parray[unit];
    680 
    681     ipmc_p->tx_vlan = (uint32*) sal_alloc(ipmc_p->num_streams * sizeof(uint32),
    682                                           "tx_vlan");
    683 
    684     ipmc_p->exp_vlan = (uint32*) sal_alloc(ipmc_p->num_streams * sizeof(uint32),
    685                                           "exp_vlan");
    686 
    687     ipmc_p->exp_mac_addr = sal_alloc(ipmc_p->num_streams *
    688                                         sizeof(uint8) * NUM_BYTES_MAC_ADDR,
    689                                                 "exp_mac_addr");
    690     BCM_PBMP_CLEAR(ubm);
    691 
    692     bcm_vlan_destroy_all(unit);
    693     bcm_vlan_control_set(unit, bcmVlanTranslate, TRUE);
    694     (void) bcm_switch_control_set(unit, bcmSwitchL3EgressMode, TRUE);
    695     PBMP_ITER(PBMP_PORT_ALL(unit), p) {
    696         (void) bcm_port_control_set(unit, p, bcmPortControlIP4, TRUE);
    697         (void) bcm_port_control_set(unit, p, bcmPortControlIP6, TRUE);
    698         (void) bcm_port_control_set(unit, p, bcmSwitchL3McIdxRetType, TRUE);
    699         (void) bcm_port_control_set(unit, p,
    700                                     bcmSwitchIpmcReplicationSharing, TRUE);
    701     }
    702 
    703     bcm_ipmc_enable(unit, TRUE);
    704     bcm_vlan_create(unit, (bcm_vlan_t)(DROP_VLAN));
    705 
    706     mc_group = (bcm_multicast_t)(FIRST_MC_GROUP);
    707     mc_flags = BCM_MULTICAST_TYPE_L3 | BCM_MULTICAST_WITH_ID;
    708     intf_id  = (bcm_if_t)(FIRST_INTF_ID);
    709     intf_flags |= BCM_L3_WITH_ID;
    710     ipmc_flags |= BCM_IPMC_SOURCE_PORT_NOCHECK;
    711 
    712     for (i = 0; i < ipmc_p->num_streams; i++) {
    713         if (ipmc_p->l3_copy[ipmc_p->stream[i][1]] == 0) {
    714             l3_stream = 0;
    715         } else {
    716             l3_stream = 1;
    717         }
    718         (void) bcm_multicast_create(unit, mc_flags, &mc_group);
    719         bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    720         BCM_PBMP_CLEAR(pbm);
    721         BCM_PBMP_PORT_ADD(pbm, ipmc_p->port_list[ipmc_p->stream[i][0]]);
    722         bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    723         vlan_0 = vlan;
    724         vlan++;
    725 
    726         bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    727         BCM_PBMP_CLEAR(pbm);
    728         for (j = 0; j < (ipmc_p->num_copy + 1); j++) {
    729             if (ipmc_p->l3_copy[ipmc_p->stream[i][j]] == 0) {
    730                 BCM_PBMP_PORT_ADD(pbm, ipmc_p->port_list[ipmc_p->stream[i][j]]);
    731                 BCM_GPORT_LOCAL_SET(gport,
    732                                     ipmc_p->port_list[ipmc_p->stream[i][j]]);
    733                 bcm_multicast_egress_add(unit, mc_group, gport,(bcm_if_t)(-1));
    734                 if ((j > 0 && l3_stream == 1) || (j > 1 && l3_stream == 0)) {
    735                     bcm_vlan_translate_add(unit,
    736                                     ipmc_p->port_list[ipmc_p->stream[i][j]],
    737                                     (bcm_vlan_t)(vlan),
    738                                     (bcm_vlan_t)(DROP_VLAN), 0);
    739                 }
    740             }
    741         }
    742         bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    743         vlan_1 = vlan;
    744         vlan++;
    745 
    746         bcm_vlan_translate_add(unit, ipmc_p->port_list[ipmc_p->stream[i][0]],
    747                                (bcm_vlan_t)(vlan_0), (bcm_vlan_t)(vlan_1), 0);
    748 
    749         if (l3_stream == 0) {
    750             bcm_vlan_translate_add(unit, ipmc_p->port_list[ipmc_p->stream[i][1]],
    751                                (bcm_vlan_t)(vlan_1), (bcm_vlan_t)(vlan_0), 0);
    752         } else {
    753             bcm_vlan_translate_add(unit, ipmc_p->port_list[ipmc_p->stream[i][1]],
    754                                (bcm_vlan_t)(vlan_1), (bcm_vlan_t)(DROP_VLAN), 0);
    755         }
    756 
    757         for (j = 0; j < (ipmc_p->num_copy + 1); j++) {
    758             if (ipmc_p->l3_copy[ipmc_p->stream[i][j]] == 1) {
    759                 for (k = 0;
    760                      k < (ipmc_p->num_rep[ipmc_p->stream[i][j]] + 1);
    761                      k++) {
    762                     BCM_PBMP_CLEAR(pbm);
    763                     BCM_PBMP_PORT_ADD(pbm,
    764                                       ipmc_p->port_list[ipmc_p->stream[i][j]]);
    765                     bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    766                     bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    767                     intf_mac[NUM_BYTES_MAC_ADDR - 1] = intf_id;
    768                     if (l3_stream == 1 && j == 1 && k == 0) {
    769                         vlan_2 = vlan;
    770                         bcm_vlan_translate_add(unit,
    771                                     ipmc_p->port_list[ipmc_p->stream[i][1]],
    772                                     (bcm_vlan_t)(vlan_2),
    773                                     (bcm_vlan_t)(vlan_0), 0);
    774                         sal_memcpy(mac_0, intf_mac, 6);
    775                     }
    776                     else {
    777                         bcm_vlan_translate_add(unit,
    778                                     ipmc_p->port_list[ipmc_p->stream[i][j]],
    779                                     (bcm_vlan_t)(vlan),
    780                                     (bcm_vlan_t)(DROP_VLAN), 0);
    781                     }
    782                     bcm_l3_intf_t_init(&l3_intf);
    783                     sal_memcpy(l3_intf.l3a_mac_addr, intf_mac, 6);
    784                     l3_intf.l3a_vid = vlan;
    785                     l3_intf.l3a_intf_id = intf_id;
    786                     l3_intf.l3a_flags = intf_flags;
    787                     bcm_l3_intf_create(unit, &l3_intf);
    788                     bcm_multicast_l3_encap_get(unit, mc_group,
    789                                        ipmc_p->port_list[ipmc_p->stream[i][j]],
    790                                        intf_id, &encap_id);
    791                     BCM_GPORT_LOCAL_SET(gport,
    792                                     ipmc_p->port_list[ipmc_p->stream[i][j]]);
    793                     bcm_multicast_egress_add(unit, mc_group, gport, encap_id);
    794                     vlan++;
    795                     intf_id++;
    796                 }
    797             }
    798         }
    799 
    800         bcm_ipmc_addr_t_init(&ipmc_addr);
    801         ipmc_addr.mc_ip_addr = DIP;
    802         ipmc_addr.s_ip_addr = SIP;
    803         ipmc_addr.vid = vlan_1;
    804         ipmc_addr.group = mc_group;
    805         ipmc_addr.flags = ipmc_flags;
    806         bcm_ipmc_add(unit, &ipmc_addr);
    807         mc_group++;
    808 
    809         ipmc_p->tx_vlan[i] = vlan_0;
    810 
    811         if (l3_stream == 0) {
    812             ipmc_p->exp_vlan[i] = vlan_1;
    813             sal_memcpy(ipmc_p->exp_mac_addr[i], mac_sa, 6);
    814         } else {
    815             ipmc_p->exp_vlan[i] = vlan_2;
    816             sal_memcpy(ipmc_p->exp_mac_addr[i], mac_0, 6);
    817         }
    818     }
    819 }
    820 
    821 /*
    822  * Function:
    823  *      ipmc_lossless_flood_cnt
    824  * Purpose:
    825  *      Calculates number of packets that need to be sent to a port for a
    826  *      lossless swirl.
    827  * Parameters:
    828  *      unit - StrataSwitch Unit #.
    829  *      pkt_size : Packet size in bytes
    830  *      port: Test port no
    831  * Returns:
    832  *     Number of packets needed for lossless flooding
    833  */
    834 static uint32
    835 ipmc_lossless_flood_cnt(int unit, int port)
    836 {
    837     uint32 pkt_size, flood_cnt = 0;
    838     int param_flood_cnt, param_pkt_size;
    839     ipmc_t *ipmc_p = ipmc_parray[unit];
    840 
    841     param_flood_cnt = ipmc_p->flood_pkt_cnt_param;
    842     param_pkt_size = ipmc_p->pkt_size_param;
    843 
    844     if (param_flood_cnt == 0) {
    845         if (param_pkt_size == 0) {
    846             pkt_size = ENET_WC_PKT_SIZE;
    847         } else {
    848             pkt_size = param_pkt_size;
    849         }
    850         flood_cnt = stream_get_ll_flood_cnt(unit, port, pkt_size, NULL);
    851     } else {
    852         flood_cnt = param_flood_cnt;
    853     }
    854 
    855     if (flood_cnt > MAX_PKTS_PER_STREAM) {
    856         flood_cnt = MAX_PKTS_PER_STREAM;
    857     }
    858     return (flood_cnt);
    859 }
    860 
    861 /*
    862  * Function:
    863  *      ipmc_send_pkts
    864  * Purpose:
    865  *      Send packets from CPU to create a swirl on each stream. Please refer
    866  *      to item 6 of the "Test Setup" portion of the test description at the
    867  *      beginning of this file.
    868  * Parameters:
    869  *      unit - StrataSwitch Unit #.
    870  *
    871  * Returns:
    872  *     Nothing
    873  */
    874 static void
    875 ipmc_send_pkts(int unit)
    876 {
    877     uint8 mac_da[] = MAC_DA;
    878     uint8 mac_sa[] = MAC_SA;
    879     uint32 pkt_size = 0, pkt_count = 0, flood_cnt = 0;
    880     int i, port;
    881     uint32 use_random_packet_sizes = 0;
    882     ipmc_t *ipmc_p = ipmc_parray[unit];
    883     stream_pkt_t *tx_pkt;
    884 
    885     tx_pkt = sal_alloc(sizeof(stream_pkt_t), "tx_pkt");
    886     sal_memset(tx_pkt, 0, sizeof(stream_pkt_t));
    887 
    888     if (ipmc_p->pkt_size_param == 1) {
    889         use_random_packet_sizes = 1;
    890     }
    891 
    892     cli_out("\n==================================================\n");
    893     cli_out("\nSending packets ...\n\n");
    894     for (i = 0; i < ipmc_p->num_streams; i++) {
    895         port = ipmc_p->port_list[ipmc_p->stream[i][0]];
    896         flood_cnt = ipmc_lossless_flood_cnt(unit, port);
    897         if (ipmc_p->pkt_size_param == 0) {
    898             pkt_size = ENET_WC_PKT_SIZE;
    899         } else {
    900             pkt_size = ipmc_p->pkt_size_param;
    901         }
    902 
    903         tx_pkt->port = port;
    904         tx_pkt->num_pkt = flood_cnt;
    905         tx_pkt->pkt_seed = ipmc_p->pkt_seed + i;
    906         tx_pkt->pkt_size = pkt_size;
    907         tx_pkt->rand_pkt_size_en = use_random_packet_sizes;
    908         tx_pkt->rand_pkt_size = NULL;
    909         tx_pkt->tx_vlan = ipmc_p->tx_vlan[i];
    910         sal_memcpy(tx_pkt->mac_da, mac_da, NUM_BYTES_MAC_ADDR);
    911         sal_memcpy(tx_pkt->mac_sa, mac_sa, NUM_BYTES_MAC_ADDR);
    912         if (tx_pkt->rand_pkt_size_en) {
    913             tx_pkt->rand_pkt_size = ipmc_p->rand_pkt_sizes[port];
    914         }
    915         tx_pkt->l3_en   = 1;
    916         tx_pkt->ipv6_en = 0;
    917         tx_pkt->ip_da   = DIP;
    918         tx_pkt->ip_sa   = SIP;
    919         tx_pkt->ttl     = TTL;
    920         stream_tx_pkt(unit, tx_pkt);
    921 
    922         /* print */
    923         cli_out("flood_cnt for stream %0d = %0d\n", i, tx_pkt->cnt_pkt);
    924         pkt_count += tx_pkt->cnt_pkt;
    925     }
    926 
    927     cli_out("\nTotal packet sent: %0d\n\n", pkt_count);
    928     sal_free(tx_pkt);
    929 }
    930 
    931 /*
    932  * Function:
    933  *      ipmc_set_up_ports
    934  * Purpose:
    935  *      Disable TTL decrement and TTL check. This makes sure the stream does not
    936  *      die out.
    937  *
    938  * Parameters:
    939  *      unit - StrataSwitch Unit #.
    940  *
    941  * Returns:
    942  *     Nothing
    943  */
    944 static void
    945 ipmc_set_up_ports(int unit)
    946 {
    947     int p;
    948     if (SOC_REG_IS_VALID(unit, EGR_IPMC_CFG2r)) {
    949         PBMP_ITER(PBMP_PORT_ALL(unit), p) {
    950             soc_reg_field32_modify(unit, EGR_IPMC_CFG2r, p,
    951                                 DISABLE_TTL_DECREMENTf, 0x1);
    952             soc_reg_field32_modify(unit, EGR_IPMC_CFG2r, p,
    953                                 DISABLE_TTL_CHECKf, 0x1);
    954         }
    955     } else {
    956         cli_out("\n*ERROR, invalid reg %s\n",
    957                 SOC_REG_NAME(unit, EGR_IPMC_CFG2r));
    958     }
    959 }
    960 
    961 /*
    962  * Function:
    963  *      ipmc_chk_port_rate
    964  * Purpose:
    965  *      Check actual port rates against expected port rates.
    966  * Parameters:
    967  *      unit - StrataSwitch Unit #.
    968  *
    969  * Returns:
    970  *     SOC_E_XXXX
    971  */
    972 static bcm_error_t
    973 ipmc_chk_port_rate(int unit)
    974 {
    975     int i, j, port, port_idx;
    976     bcm_error_t rv = BCM_E_NONE;
    977     stream_rate_t *rate_calc;
    978     ipmc_t *ipmc_p = ipmc_parray[unit];
    979 
    980     rate_calc = (stream_rate_t *)
    981                  sal_alloc(sizeof(stream_rate_t), "rate_calc");
    982     if (rate_calc == NULL) {
    983         test_error(unit, "Failed to allocate memory for rate_calc\n");
    984         return BCM_E_FAIL;
    985     }
    986     sal_memset(rate_calc, 0, sizeof(stream_rate_t));
    987 
    988     rate_calc->mode         = 1;
    989     rate_calc->pkt_size     = ipmc_p->pkt_size_param;
    990     rate_calc->interval_len = ipmc_p->run_time_param;
    991     rate_calc->tolerance_lr = PKT_COUNT_CHECK_TOL;
    992     rate_calc->tolerance_os = PKT_COUNT_CHECK_TOL;
    993     rate_calc->scaling_factor = ipmc_p->scaling_factor_param;
    994 
    995     SOC_PBMP_CLEAR(rate_calc->pbmp);
    996     for (i = 0; i < ipmc_p->num_streams; i++) {
    997         for (j = 0; j < (ipmc_p->num_copy + 1); j++) {
    998             port_idx = ipmc_p->stream[i][j];
    999             port = ipmc_p->port_list[port_idx];
   1000             if (port < SOC_MAX_NUM_PORTS) {
   1001                 /* pbmp */
   1002                 SOC_PBMP_PORT_ADD((rate_calc->pbmp), port);
   1003                 /* num_l3_rep */
   1004                 if (ipmc_p->l3_copy[port_idx] == 0) {
   1005                     rate_calc->num_rep[port] = 0;
   1006                 } else {
   1007                     rate_calc->num_rep[port] = ipmc_p->num_rep[port_idx] + 1;
   1008                 }
   1009                 /* src_port */
   1010                 rate_calc->src_port[port] =
   1011                         ipmc_p->port_list[ipmc_p->stream[i][0]];
   1012             }
   1013         }
   1014     }
   1015 
   1016     rv = stream_chk_port_rate(unit, PBMP_PORT_ALL(unit), rate_calc);
   1017 
   1018     sal_free(rate_calc);
   1019     return rv;
   1020 }
   1021 
   1022 /*
   1023  * Function:
   1024  *      ipmc_chk_pkt_integrity
   1025  * Purpose:
   1026  *      Redirect all packets back to CPU and check packet integrity
   1027  * Parameters:
   1028  *      unit - StrataSwitch Unit #.
   1029  *
   1030  * Returns:
   1031  *     Nothing
   1032  */
   1033 static bcm_error_t
   1034 ipmc_chk_pkt_integrity(int unit)
   1035 {
   1036     int i, port, vlan_id;
   1037     int param_num_stream, param_pkt_seed;
   1038     int *param_port_list, **param_stream;
   1039     uint32 flood_cnt;
   1040     uint8 mac_da[] = MAC_DA;
   1041     /* uint8 mac_sa[] = MAC_SA; */
   1042     stream_integrity_t *pkt_intg;
   1043     bcm_error_t rv = BCM_E_NONE;
   1044     ipmc_t *ipmc_p = ipmc_parray[unit];
   1045 
   1046     param_num_stream = ipmc_p->num_streams;
   1047     param_pkt_seed = ipmc_p->pkt_seed;
   1048     param_port_list = ipmc_p->port_list;
   1049     param_stream = ipmc_p->stream;
   1050 
   1051     pkt_intg = sal_alloc(sizeof(stream_integrity_t), "pkt_intg");
   1052     if (pkt_intg == NULL) {
   1053         test_error(unit, "Failed to allocate memory for pkt_intg\n");
   1054         return BCM_E_FAIL;
   1055     }
   1056     sal_memset(pkt_intg, 0, sizeof(stream_integrity_t));
   1057 
   1058     pkt_intg->type = PKT_TYPE_IPMC;
   1059     pkt_intg->ipv6_en = 0;
   1060     SOC_PBMP_CLEAR(pkt_intg->rx_pbmp);
   1061     for (i = 0; i < param_num_stream; i++) {
   1062         port = param_port_list[param_stream[i][0]];
   1063         if (port < SOC_MAX_NUM_PORTS) {
   1064             /* rx_pbmp */
   1065             SOC_PBMP_PORT_ADD(pkt_intg->rx_pbmp, port);
   1066             /* rx_vlan: used to forward pkt to CPU */
   1067             vlan_id = ipmc_p->tx_vlan[i];
   1068             pkt_intg->rx_vlan[port] = vlan_id;
   1069             /* tx_vlan: used to re-generate ref_pkt */
   1070             vlan_id = ipmc_p->exp_vlan[i];
   1071             pkt_intg->tx_vlan[port] = vlan_id;
   1072             /* port_flood_cnt */
   1073             flood_cnt = ipmc_lossless_flood_cnt(unit, port);
   1074             pkt_intg->port_flood_cnt[port] = flood_cnt;
   1075             /* port_pkt_seed */
   1076             pkt_intg->port_pkt_seed[port] = param_pkt_seed + i;
   1077             /* mac_da, mac_sa */
   1078             sal_memcpy(pkt_intg->mac_da[port], mac_da, NUM_BYTES_MAC_ADDR);
   1079             sal_memcpy(pkt_intg->mac_sa[port], ipmc_p->exp_mac_addr[i], NUM_BYTES_MAC_ADDR);
   1080             /* ip_da, ip_sa */
   1081             pkt_intg->ip_da[port] = DIP;
   1082             pkt_intg->ip_sa[port] = SIP;
   1083         }
   1084     }
   1085 
   1086     if (stream_chk_pkt_integrity(unit, pkt_intg) != BCM_E_NONE) {
   1087         rv = BCM_E_FAIL;
   1088     }
   1089 
   1090     sal_free(pkt_intg);
   1091     return rv;
   1092 }
   1093 
   1094 /*
   1095  * Function:
   1096  *      ipmc_free_all_memory
   1097  * Purpose:
   1098  *      Free all allocated memory.
   1099  * Parameters:
   1100  *      unit - StrataSwitch Unit #.
   1101  *
   1102  * Returns:
   1103  *     Nothing
   1104  */
   1105 static void
   1106 ipmc_free_all_memory(int unit)
   1107 {
   1108     int i;
   1109     ipmc_t *ipmc_p = ipmc_parray[unit];
   1110 
   1111     sal_free(ipmc_p->port_speed);
   1112     sal_free(ipmc_p->port_list);
   1113     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
   1114         sal_free(ipmc_p->stream[i]);
   1115     }
   1116     sal_free(ipmc_p->stream);
   1117     sal_free(ipmc_p->num_rep);
   1118     sal_free(ipmc_p->l3_copy);
   1119     sal_free(ipmc_p->tx_vlan);
   1120     sal_free(ipmc_p->exp_vlan);
   1121     sal_free(ipmc_p->exp_mac_addr);
   1122     sal_free(ipmc_p->port_oversub);
   1123     sal_free(ipmc_p->port_used);
   1124     sal_free(ipmc_p->ovs_ratio_x1000);
   1125     sal_free(ipmc_p->exp_rate);
   1126     sal_free(ipmc_p->tpkt_start);
   1127     sal_free(ipmc_p->tpkt_end);
   1128     for (i = 0; i < ipmc_p->num_fp_ports; i++) {
   1129         sal_free(ipmc_p->rand_pkt_sizes[i]);
   1130     }
   1131     sal_free(ipmc_p->rand_pkt_sizes);
   1132 }
   1133 
   1134 /*
   1135  * Function:
   1136  *      ipmc_test_init
   1137  * Purpose:
   1138  *      Test init function. Parse CLI params and do necessary init.
   1139  * Parameters:
   1140  *      unit - StrataSwitch Unit #.
   1141  *
   1142  * Returns:
   1143  *     Nothing
   1144  */
   1145 int
   1146 ipmc_test_init(int unit, args_t *a, void **pa)
   1147 {
   1148     ipmc_t *ipmc_p;
   1149 
   1150     ipmc_p = ipmc_parray[unit];
   1151     ipmc_p = sal_alloc(sizeof(ipmc_t), "ipmc_test");
   1152     sal_memset(ipmc_p, 0, sizeof(ipmc_t));
   1153     ipmc_parray[unit] = ipmc_p;
   1154 
   1155     stream_print_port_config(unit, PBMP_PORT_ALL(unit));
   1156     cli_out("\n==================================================");
   1157     cli_out("\nCalling ipmc_test_init ...\n");
   1158     ipmc_parse_test_params(unit, a);
   1159 
   1160     ipmc_p->test_fail = 0;
   1161 
   1162     if (ipmc_p->bad_input == 1) {
   1163         goto done;
   1164     }
   1165 
   1166     stream_set_mac_lpbk(unit, PBMP_PORT_ALL(unit));
   1167     stream_turn_off_cmic_mmu_bkp(unit);
   1168     stream_turn_off_fc(unit, PBMP_PORT_ALL(unit));
   1169     /* coverity[dont_call : FALSE] */
   1170     ipmc_p->pkt_seed = sal_rand();
   1171 
   1172 done:
   1173     return 0;
   1174 }
   1175 
   1176 /*
   1177  * Function:
   1178  *      ipmc_test
   1179  * Purpose:
   1180  *      Set up ports/streams and send packets.
   1181  * Parameters:
   1182  *      unit - StrataSwitch Unit #.
   1183  *
   1184  * Returns:
   1185  *     Nothing
   1186  */
   1187 int
   1188 ipmc_test(int unit, args_t *a, void *pa)
   1189 {
   1190     ipmc_t *ipmc_p = ipmc_parray[unit];
   1191 
   1192     if (ipmc_p->bad_input == 1) {
   1193         goto done;
   1194     }
   1195 
   1196     cli_out("\n==================================================");
   1197     cli_out("\nCalling ipmc_test ... \n");
   1198     ipmc_set_port_property(unit);
   1199     ipmc_set_up_ports(unit);
   1200     ipmc_set_up_streams(unit);
   1201     ipmc_send_pkts(unit);
   1202 
   1203     /* check counter */
   1204     if (stream_chk_mib_counters(unit, PBMP_PORT_ALL(unit), 0) != BCM_E_NONE) {
   1205         ipmc_p->test_fail = 1;
   1206     }
   1207     /* check rate */
   1208     if (ipmc_chk_port_rate(unit) != BCM_E_NONE) {
   1209         ipmc_p->test_fail = 1;
   1210     }
   1211     /* check integrity */
   1212     if (ipmc_chk_pkt_integrity(unit) != BCM_E_NONE) {
   1213         ipmc_p->test_fail = 1;
   1214     }
   1215 
   1216 done:
   1217     return 0;
   1218 }
   1219 
   1220 /*
   1221  * Function:
   1222  *      ipmc_test_cleanup
   1223  * Purpose:
   1224  *      Do test end checks and free all allocated memory.
   1225  * Parameters:
   1226  *      unit - StrataSwitch Unit #.
   1227  *
   1228  * Returns:
   1229  *     Nothing
   1230  */
   1231 int
   1232 ipmc_test_cleanup(int unit, void *pa)
   1233 {
   1234     int rv;
   1235     ipmc_t *ipmc_p = ipmc_parray[unit];
   1236 
   1237     if (ipmc_p->bad_input == 1) {
   1238         goto done;
   1239     }
   1240     cli_out("\nCalling ipmc_test_cleanup");
   1241 
   1242 done:
   1243     if (ipmc_p->bad_input == 1) {
   1244         ipmc_p->test_fail = 1;
   1245     }
   1246 
   1247     if (ipmc_p->test_fail == 1) {
   1248         rv = BCM_E_FAIL;
   1249     }
   1250     else {
   1251         rv = BCM_E_NONE;
   1252     }
   1253 
   1254     cli_out("\n==================================================");
   1255     cli_out("\n==================================================");
   1256     if (ipmc_p->test_fail == 1) {
   1257         cli_out("\n[IPMC test failed]\n\n");
   1258     } else {
   1259         cli_out("\n[IPMC test passed]\n\n");
   1260     }
   1261 
   1262     ipmc_free_all_memory(unit);
   1263     sal_free(ipmc_p);
   1264 
   1265     return rv;
   1266 }
   1267 
   1268 #endif /* BCM_ESW_SUPPORT && INCLUDE_L3 */