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_l2mc.c (45344B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * The goal of this test is to check basic multicast and broadcast features of
      8  * the chip.
      9  * Test Sequence:
     10  * 1. Group all active front panel ports into groups of (NumCopy + 1) ports.
     11  *    Each group constitutes 1 multicast "stream". All ports in a stream should
     12  *    either be Ethernet or HG2 and have the same line rate, although they may
     13  *    have different oversub ratios.
     14  * 2. Let us assume a stream has n ports P0, P1 ... Pn. The ports should be
     15  *    arranged such that the P1 is the slowest port, i.e. has the highest
     16  *    oversub ratio.
     17  * 3. Turn off all flow control, set MAC loopback on all ports and set
     18  *    IGNORE_MY_MODID to 1 on ING_CONFIG_64.
     19  * 4. For Ethernet streams:
     20  *      a.  Place all ports in the stream on a single VLAN, say VLAN0.
     21  *      b.  Place ports P0 and P1 on a second VLAN, say VLAN1.
     22  *      c.  Create a 3rd VLAN, say VLAN3 with no ports on it.
     23  *      d.  Add the following VLAN translations:
     24  *          i.  Port=P0 OldVlan=VLAN1 NewVlan=VLAN0
     25  *          ii. Port=P1 OldVlan=VLAN0 NewVlan=VLAN1
     26  *          iii.    Ports=P2, P3 ... Pn OldVlan=VLAN0 NewVlan=VLAN2
     27  * 5. For HG2 streams:
     28  *      a.  Place port P0 on VLAN0.
     29  *      b.  Place ports P0, P1 ... Pn on VLAN1.
     30  *      c.  Place all ports in the stream except P0, i.e. P1, P2 ... Pn on VLAN2
     31  *      d.  Create 3 entries, say L2MC0, L2MC1 and L2MC2.
     32  *          i.  L2MC0: PORT_BITMAP = P0
     33  *          ii. L2MC1: PORT_BITMAP = P0
     34  *          iii.    L2MC2: PORT_BITMAP = P1, P2 ... Pn
     35  *      e.  Add the following IFP entries:
     36  *          i.  Qualifier: OuterVlan=VLAN0, Actions: OuterVlanNew=VLAN1, RedirectMcast=L2MC0
     37  *          ii. Qualifier: OuterVlan=VLAN2, Actions: OuterVlanNew=VLAN1, RedirectMcast=L2MC1
     38  *          iii.Qualifier: OuterVlan=VLAN1, Actions: OuterVlanNew=VLAN2, RedirectMcast=L2MC2
     39  * 6. Send packets from CPU port on VLAN0 of each stream to flood the stream.
     40  *    If FloodCnt=0, the test will determine the number of packets to send based.
     41  *    These values are obtained empirically through trial and error for LR ports
     42  *    for NumCopy=2 and adjusted for oversub configs based on oversub ratio.
     43  *    Embed the packet size and random seed used to generate each packet in the
     44  *    payload.
     45  * 7. Allow the packets to swill for a fixed amount of time decided by RateCalcInt.
     46  * 8. Snoop back all packets in each stream to the CPU using the following sequence:
     47  *      a.  Program CPU_CONTROL_0.UVLAN_TOCPU=1. This sends all packets with an
     48  *          unknown VLAN to CPU.
     49  *      b.  Invalidate VLAN0 for Ethernet Streams and VLAN1 for HG2 streams by
     50  *          setting VALID=0 in the VLAN table
     51  * 9. Decode each received packet to obtain the random seed and packet size.
     52  *    Reconstruct the expected packet and check the received packet for integrity.
     53  *
     54  * Configuration parameters passed from CLI:
     55  * PktSize: Packet size in bytes. Set to 0 for worst case packet sizes on all
     56  *          ports (145B for ENET, 76B for HG2). Set to 1 for random packet sizes
     57  * FloodCnt: Number of packets in each swill. Setting this to 0 will let the
     58  *           test calculate the number of packets that can be sent to achieve
     59  *           a lossless swirl at full rate. Set to 0 by default.
     60  * NumCopy: Number of multicast copies in each stream (2 by default).
     61  * RateCalcInt: Interval in seconds over which rate is to be calculated
     62  * TolLr: Rate tolerance percentage for linerate ports (1% by default).
     63  * TolOv: Rate tolerance percentage for oversubscribed ports (3% by default).
     64  * ChkPktInteg: Set to 0 to disable packet integrity checks, 1 to enable (default).
     65  * MaxNumCells: Max number of cells for random packet sizes. Default = 4. Set
     66  *              to 0 for random.
     67  */
     68 
     69 #include <appl/diag/system.h>
     70 #include <shared/alloc.h>
     71 #include <shared/bsl.h>
     72 
     73 #include <soc/cm.h>
     74 #include <soc/dma.h>
     75 #include <soc/drv.h>
     76 #include <soc/dcb.h>
     77 #include <soc/cmicm.h>
     78 #include <soc/cmic.h>
     79 
     80 #include <sal/types.h>
     81 #include <appl/diag/parse.h>
     82 #include <bcm/port.h>
     83 #include <bcm/vlan.h>
     84 #include <bcm/link.h>
     85 
     86 #include "testlist.h"
     87 #include "gen_pkt.h"
     88 #include "streaming_lib.h"
     89 
     90 #define MAC_DA {0x01,0x00,0x0c,0xde,0xff,0x00}
     91 #define MAC_SA {0xfe,0xdc,0xba,0x98,0x76,0x54}
     92 #define VLAN 0x100
     93 
     94 #define MAX_FP_PORTS 130
     95 #define MAX_NUM_CELLS_PARAM_DEFAULT 4
     96 
     97 #define FLOOD_CNT_25G 9
     98 #define FLOOD_CNT_40G 21
     99 #define FLOOD_CNT_50G 28
    100 #define FLOOD_CNT_100G 50
    101 
    102 #define MAX_PKTS_PER_STREAM 500
    103 
    104 #define PKT_SIZE_PARAM_DEFAULT 0
    105 #define FLOOD_PKT_CNT_PARAM_DEFAULT 0
    106 #define NUM_COPY_PARAM_DEFAULT 2
    107 #define RATE_CALC_INTERVAL_PARAM_DEFAULT 10
    108 #define RATE_TOLERANCE_LR_PARAM_DEFAULT 1
    109 #define RATE_TOLERANCE_OV_PARAM_DEFAULT 3
    110 #define CHECK_PACKET_INTEGRITY_PARAM_DEFAULT 1
    111 #define SPEEDUP_FACTOR_PARAM_DEFAULT 1
    112 #define NUM_LPORT_TAB_ENTRIES 256
    113 #define NUM_PORT_TAB_ENTRIES 136
    114 #define CPU_PORT 0
    115 
    116 #if defined(BCM_ESW_SUPPORT) && \
    117    (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT))
    118 
    119 typedef struct l2mc_s {
    120 
    121     uint32 num_fp_ports;
    122     uint32 num_streams;
    123     int *port_speed;
    124     int *port_list;
    125     int **stream;
    126     uint32 *tx_vlan;
    127     int *hg_stream;
    128     uint32 *port_oversub;
    129     uint32 oversub_config;
    130     uint32 *port_used;
    131     uint32 num_pipes;
    132     uint32 total_chip_bw;
    133     uint32 bw_per_pipe;
    134     uint32 *ovs_ratio_x1000;
    135     uint64 *rate;
    136     uint64 *exp_rate;
    137     uint64 *tpkt_start;
    138     uint64 *tpkt_end;
    139     uint64 *tbyt_start;
    140     uint64 *tbyt_end;
    141     uint32 **rand_pkt_sizes;
    142     uint32 pkt_size_param;
    143     uint32 flood_pkt_cnt_param;
    144     uint32 num_copy_param;
    145     uint32 rate_calc_interval_param;
    146     uint32 rate_tolerance_lr_param;
    147     uint32 rate_tolerance_ov_param;
    148     uint32 check_packet_integrity_param;
    149     uint32 max_num_cells_param;
    150     uint32 scaling_factor_param;
    151     uint32 bad_input;
    152     int test_fail;
    153     uint32 pkt_seed;
    154 } l2mc_t;
    155 
    156 static l2mc_t *l2mc_parray[SOC_MAX_NUM_DEVICES];
    157 
    158 /*
    159  * Function:
    160  *      l2mc_print_port_config
    161  * Purpose:
    162  *      Print port config
    163  * Parameters:
    164  *      unit - StrataSwitch Unit #.
    165  *
    166  * Returns:
    167  *     Nothing
    168  */
    169 static void
    170 l2mc_print_port_config(int unit)
    171 {
    172     int i, port;
    173     pbmp_t pbmp;
    174     l2mc_t *l2mc_p = l2mc_parray[unit];
    175 
    176     SOC_PBMP_CLEAR(pbmp);
    177     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    178         port = l2mc_p->port_list[i];
    179         if (port < SOC_MAX_NUM_PORTS) {
    180             SOC_PBMP_PORT_ADD(pbmp, port);
    181         }
    182     }
    183     stream_print_port_config(unit, pbmp);
    184 }
    185 
    186 /*
    187  * Function:
    188  *      l2mc_parse_test_params
    189  * Purpose:
    190  *      Parse CLI parameters, create test structure and flag bad inputs.
    191  * Parameters:
    192  *      unit - StrataSwitch Unit #.
    193  *      a - Pointer to arguments
    194  *
    195  * Returns:
    196  *     Nothing
    197  * Notes:
    198  *      l2mc_p->bad_input set from here - tells test to crash out in case
    199  *      CLI input combination is invalid.
    200  */
    201 static void
    202 l2mc_parse_test_params(int unit, args_t *a)
    203 {
    204     parse_table_t parse_table;
    205     l2mc_t *l2mc_p = l2mc_parray[unit];
    206 
    207     const char tr511_test_usage[] =
    208 #ifdef COMPILER_STRING_CONST_LIMIT
    209     "\nDocumentation too long to be displayed with -pedantic compiler\n";
    210 #else
    211     "The goal of this test is to check basic multicast and broadcast features of\n"
    212     "the chip.\n"
    213     "Test Sequence:\n"
    214     "1. Group all active front panel ports into groups of (NumCopy + 1) ports.\n"
    215     "    Each group constitutes 1 multicast \"stream\". All ports in a stream should\n"
    216     "    either be Ethernet or HG2 and have the same line rate, although they may\n"
    217     "    have different oversub ratios.\n"
    218     "2. Let us assume a stream has n ports P0, P1 ... Pn. The ports should be\n"
    219     "    arranged such that the P1 is the slowest port, i.e. has the highest\n"
    220     "    oversub ratio.\n"
    221     "3. Turn off all flow control, set MAC loopback on all ports and set\n"
    222     "    IGNORE_MY_MODID to 1 on ING_CONFIG_64.\n"
    223     "4. For Ethernet streams:\n"
    224     "    a.  Place all ports in the stream on a single VLAN, say VLAN0.\n"
    225     "    b.  Place ports P0 and P1 on a second VLAN, say VLAN1.\n"
    226     "    c.  Create a 3rd VLAN, say VLAN3 with no ports on it.\n"
    227     "    d.  Add the following VLAN translations:\n"
    228     "        i.  Port=P0 OldVlan=VLAN1 NewVlan=VLAN0\n"
    229     "        ii. Port=P1 OldVlan=VLAN0 NewVlan=VLAN1\n"
    230     "        iii.    Ports=P2, P3 ... Pn OldVlan=VLAN0 NewVlan=VLAN2\n"
    231     "5. For HG2 streams:\n"
    232     "    a.  Place port P0 on VLAN0.\n"
    233     "    b.  Place ports P0, P1 ... Pn on VLAN1.\n"
    234     "    c.  Place all ports in the stream except P0, i.e. P1, P2 ... Pn on VLAN2\n"
    235     "    d.  Create 3 entries, say L2MC0, L2MC1 and L2MC2.\n"
    236     "        i.  L2MC0: PORT_BITMAP = P0\n"
    237     "        ii. L2MC1: PORT_BITMAP = P0\n"
    238     "        iii.    L2MC2: PORT_BITMAP = P1, P2 ... Pn\n"
    239     "    e.  Add the following IFP entries:\n"
    240     "        i.  Qualifier: OuterVlan=VLAN0, Actions: OuterVlanNew=VLAN1, RedirectMcast=L2MC0\n"
    241     "        ii. Qualifier: OuterVlan=VLAN2, Actions: OuterVlanNew=VLAN1, RedirectMcast=L2MC1\n"
    242     "        iii.    Qualifier: OuterVlan=VLAN1, Actions: OuterVlanNew=VLAN2, RedirectMcast=L2MC2\n"
    243     "6. Send packets from CPU port on VLAN0 of each stream to flood the stream.\n"
    244     "    If FloodCnt=0, the test will determine the number of packets to send based.\n"
    245     "    These values are obtained empirically through trial and error for LR ports\n"
    246     "    for NumCopy=2 and adjusted for oversub configs based on oversub ratio.\n"
    247     "    Embed the packet size and random seed used to generate each packet in the\n"
    248     "    payload.\n"
    249     "7. Allow the packets to swill for a fixed amount of time decided by RateCalcInt.\n"
    250     "8. Snoop back all packets in each stream to the CPU using the following sequence:\n"
    251     "    a.  Program CPU_CONTROL_0.UVLAN_TOCPU=1. This sends all packets with an\n"
    252     "        unknown VLAN to CPU.\n"
    253     "    b.  Invalidate VLAN0 for Ethernet Streams and VLAN1 for HG2 streams by\n"
    254     "        setting VALID=0 in the VLAN table\n"
    255     "9. Decode each received packet to obtain the random seed and packet size.\n"
    256     "    Reconstruct the expected packet and check the received packet for integrity.\n"
    257     "\n"
    258     "Configuration parameters passed from CLI:\n"
    259     "PktSize: Packet size in bytes. Set to 0 for worst case packet sizes on all\n"
    260     "         ports (145B for ENET, 76B for HG2). Set to 1 for random packet sizes\n"
    261     "FloodCnt: Number of packets in each swill. Setting this to 0 will let the\n"
    262     "          test calculate the number of packets that can be sent to achieve\n"
    263     "          a lossless swirl at full rate. Set to 0 by default.\n"
    264     "NumCopy: Number of multicast copies in each stream (2 by default).\n"
    265     "RateCalcInt: Interval in seconds over which rate is to be calculated\n"
    266     "TolLr: Rate tolerance percentage for linerate ports (1 percentage by default).\n"
    267     "TolOv: Rate tolerance percentage for oversubscribed ports (3 percentage by default).\n"
    268     "ChkPktInteg: Set to 0 to disable packet integrity checks, 1 to enable (default).\n"
    269     "MaxNumCells: Max number of cells for random packet sizes. Default = 4. Set\n"
    270     "             to 0 for random.\n";
    271 #endif
    272 
    273     l2mc_p->bad_input = 0;
    274 
    275     l2mc_p->pkt_size_param = PKT_SIZE_PARAM_DEFAULT;
    276     l2mc_p->flood_pkt_cnt_param = FLOOD_PKT_CNT_PARAM_DEFAULT;
    277     l2mc_p->num_copy_param = NUM_COPY_PARAM_DEFAULT;
    278     l2mc_p->rate_calc_interval_param = RATE_CALC_INTERVAL_PARAM_DEFAULT;
    279     l2mc_p->rate_tolerance_lr_param = RATE_TOLERANCE_LR_PARAM_DEFAULT;
    280     l2mc_p->rate_tolerance_ov_param = RATE_TOLERANCE_OV_PARAM_DEFAULT;
    281     l2mc_p->check_packet_integrity_param
    282                             = CHECK_PACKET_INTEGRITY_PARAM_DEFAULT;
    283     l2mc_p->max_num_cells_param = MAX_NUM_CELLS_PARAM_DEFAULT;
    284     l2mc_p->scaling_factor_param = SPEEDUP_FACTOR_PARAM_DEFAULT;
    285 
    286     /*Parse CLI opts */
    287 
    288     parse_table_init(unit, &parse_table);
    289     parse_table_add(&parse_table, "PktSize", PQ_INT|PQ_DFL, 0,
    290                     &(l2mc_p->pkt_size_param), NULL);
    291     parse_table_add(&parse_table, "FloodCnt", PQ_INT|PQ_DFL, 0,
    292                     &(l2mc_p->flood_pkt_cnt_param), NULL);
    293     parse_table_add(&parse_table, "NumCopy", PQ_INT|PQ_DFL, 0,
    294                     &(l2mc_p->num_copy_param), NULL);
    295     parse_table_add(&parse_table, "RateCalcInt", PQ_INT|PQ_DFL, 0,
    296                     &(l2mc_p->rate_calc_interval_param), NULL);
    297     parse_table_add(&parse_table, "TolLr", PQ_INT|PQ_DFL, 0,
    298                     &(l2mc_p->rate_tolerance_lr_param), NULL);
    299     parse_table_add(&parse_table, "TolOv", PQ_INT|PQ_DFL, 0,
    300                     &(l2mc_p->rate_tolerance_ov_param), NULL);
    301     parse_table_add(&parse_table, "ChkPktInteg", PQ_INT|PQ_DFL, 0,
    302                     &(l2mc_p->check_packet_integrity_param), NULL);
    303     parse_table_add(&parse_table, "MaxNumCells", PQ_INT|PQ_DFL, 0,
    304                     &(l2mc_p->max_num_cells_param), NULL);
    305     parse_table_add(&parse_table, "ScalingFactor", PQ_INT|PQ_DFL, 0,
    306                     &(l2mc_p->scaling_factor_param), NULL);
    307 
    308     if (parse_arg_eq(a, &parse_table) < 0 || ARG_CNT(a) != 0) {
    309         test_msg("%s", tr511_test_usage);
    310         test_error(unit,
    311                    "%s: Invalid option: %s\n",
    312                    ARG_CMD(a),
    313                    ARG_CUR(a) ? ARG_CUR(a) : "*");
    314         l2mc_p->bad_input = 1;
    315         parse_arg_eq_done(&parse_table);
    316     } else {
    317         cli_out("\n");
    318         cli_out("------------- PRINTING TEST PARAMS ------------------\n");
    319         cli_out("PktSize      = %0d\n", l2mc_p->pkt_size_param);
    320         cli_out("FloodCnt     = %0d\n", l2mc_p->flood_pkt_cnt_param);
    321         cli_out("NumCopy      = %0d\n", l2mc_p->num_copy_param);
    322         cli_out("RateCalcInt  = %0d\n", l2mc_p->rate_calc_interval_param);
    323         cli_out("TolLr        = %0d\n", l2mc_p->rate_tolerance_lr_param);
    324         cli_out("TolOv        = %0d\n", l2mc_p->rate_tolerance_ov_param);
    325         cli_out("ChkPktInteg  = %0d\n", l2mc_p->check_packet_integrity_param);
    326         cli_out("MaxNumCells  = %0d\n", l2mc_p->max_num_cells_param);
    327         cli_out("ScalingFactor= %0d\n", l2mc_p->scaling_factor_param);
    328         cli_out("-----------------------------------------------------\n");
    329     }
    330 
    331     if (l2mc_p->max_num_cells_param == 0) {
    332         /* coverity[dont_call : FALSE] */
    333         l2mc_p->max_num_cells_param = (sal_rand() % (MTU_CELL_CNT - 1)) + 1;
    334     }
    335 
    336     if (l2mc_p->pkt_size_param == 0) {
    337         cli_out
    338             ("\nUsing worst case packet sizes - 145B for Ethernet "
    339              "and 76B (64B + 12B hg-hdr) for HG2");
    340     } else if (l2mc_p->pkt_size_param == 1) {
    341         cli_out("\nUsing random packet sizes");
    342     } else if (l2mc_p->pkt_size_param < MIN_PKT_SIZE) {
    343         test_error(unit,"\n*ERROR: Packet size cannot be lower than %0dB\n",
    344                 MIN_PKT_SIZE);
    345         l2mc_p->bad_input = 1;
    346     } else if (l2mc_p->pkt_size_param > MTU) {
    347         test_error(unit,"\n*ERROR: Packet size cannot be higher than %0dB (Test Limitation)\n",
    348                 MTU);
    349         l2mc_p->bad_input = 1;
    350     }
    351 
    352     if (l2mc_p->flood_pkt_cnt_param == 0) {
    353         cli_out("\nFloodCnt=0, test will automatically calculate number of"
    354                 " packets to flood each port");
    355     }
    356 }
    357 
    358 /*
    359  * Function:
    360  *      l2mc_set_lowest_stream_port
    361  * Purpose:
    362  *      Within each stream, put the port with the lowest speed
    363  *      in the 2nd position.
    364  * Parameters:
    365  *      unit: StrataSwitch Unit #.
    366  *
    367  * Returns:
    368  *     Nothing
    369  */
    370 static void
    371 l2mc_set_lowest_stream_port(int unit)
    372 {
    373     int i, j, tmp, port, port_speed, min_speed, min_speed_idx;
    374     int param_idx;
    375     l2mc_t *l2mc_p = l2mc_parray[unit];
    376 
    377     param_idx = 1;
    378     for (i = 0; i < l2mc_p->num_streams; i++) {
    379         min_speed_idx = param_idx;
    380         port = l2mc_p->port_list[l2mc_p->stream[i][min_speed_idx]];
    381         bcm_port_speed_get(unit, port, &min_speed);
    382 
    383         for (j = 0; j < (l2mc_p->num_copy_param + 1); j++) {
    384             port = l2mc_p->port_list[l2mc_p->stream[i][j]];
    385             bcm_port_speed_get(unit, port, &port_speed);
    386             if (port_speed < min_speed) {
    387                 min_speed = port_speed;
    388                 min_speed_idx = j;
    389             }
    390         }
    391         if (min_speed_idx != param_idx) {
    392             tmp = l2mc_p->stream[i][param_idx];
    393             l2mc_p->stream[i][param_idx] =  l2mc_p->stream[i][min_speed_idx];
    394             l2mc_p->stream[i][min_speed_idx] = tmp;
    395         }
    396     }
    397 }
    398 
    399 /*
    400  * Function:
    401  *      l2mc_set_port_property_arrays
    402  * Purpose:
    403  *      Set port_list, port_speed
    404  * Parameters:
    405  *      unit: StrataSwitch Unit #.
    406  *
    407  * Returns:
    408  *     Nothing.
    409  */
    410 static void
    411 l2mc_set_port_property_arrays(int unit)
    412 {
    413     int p;
    414     int picked_port;
    415     int i, j;
    416     uint32 pkt_size;
    417     soc_info_t *si = &SOC_INFO(unit);
    418     uint32 stream_possible = 0;
    419     uint32 ports_found = 0;
    420     uint32 ports_picked = 0;
    421     uint32 ports_accounted_for = 0;
    422     l2mc_t *l2mc_p = l2mc_parray[unit];
    423 
    424     l2mc_p->num_fp_ports = 0;
    425     l2mc_p->num_streams = 0;
    426     l2mc_p->oversub_config = 0;
    427 
    428     PBMP_ITER(PBMP_PORT_ALL(unit), p) {
    429         l2mc_p->num_fp_ports++;
    430     }
    431 
    432     l2mc_p->port_list =
    433         (int *)sal_alloc(l2mc_p->num_fp_ports * sizeof(int),
    434                          "port_list");
    435     l2mc_p->port_speed =
    436         (int *)sal_alloc(l2mc_p->num_fp_ports * sizeof(int),
    437                          "port_speed_array");
    438     l2mc_p->hg_stream =
    439         (int *)sal_alloc(l2mc_p->num_fp_ports * sizeof(int),
    440                          "hg_stream_array");
    441     l2mc_p->port_oversub =
    442         (uint32 *) sal_alloc(l2mc_p->num_fp_ports * sizeof(uint32),
    443                              "port_oversub_array");
    444     l2mc_p->rand_pkt_sizes =
    445         (uint32 **) sal_alloc(l2mc_p->num_fp_ports * sizeof(uint32 *),
    446                               "rand_pkt_sizes_array*");
    447 
    448     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    449         l2mc_p->rand_pkt_sizes[i] =
    450             (uint32 *) sal_alloc(TARGET_CELL_COUNT * sizeof(uint32),
    451                                 "rand_pkt_sizes_array");
    452     }
    453     l2mc_p->stream =
    454         (int **) sal_alloc(l2mc_p->num_fp_ports * sizeof(int *),
    455                               "stream_array*");
    456 
    457     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    458         l2mc_p->stream[i] =
    459             (int *) sal_alloc((l2mc_p->num_copy_param + 1) * sizeof(int),
    460                                 "stream_array");
    461     }
    462     l2mc_p->port_used =
    463         (uint32 *) sal_alloc(l2mc_p->num_fp_ports * sizeof(uint32),
    464                              "l2mc_p->port_used_array");
    465 
    466     i = 0;
    467     PBMP_ITER(PBMP_PORT_ALL(unit), p) {
    468         l2mc_p->port_list[i] = p;
    469         i++;
    470     }
    471 
    472     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    473         l2mc_p->port_speed[i] =
    474             si->port_speed_max[l2mc_p->port_list[i]];
    475 
    476         switch(l2mc_p->port_speed[i]) {
    477             case 11000: l2mc_p->port_speed[i] = 10600; break;
    478             case 27000: l2mc_p->port_speed[i] = 26500; break;
    479             case 42000: l2mc_p->port_speed[i] = 42400; break;
    480             default: break;
    481         }
    482     }
    483 
    484     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    485         if (SOC_PBMP_MEMBER(si->oversub_pbm, l2mc_p->port_list[i])
    486             &&
    487             (!(SOC_PBMP_MEMBER(si->management_pbm, l2mc_p->port_list[i])))) {
    488             l2mc_p->oversub_config = 1;
    489             l2mc_p->port_oversub[i] = 1;
    490         } else {
    491             l2mc_p->port_oversub[i] = 0;
    492         }
    493     }
    494 
    495     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    496         l2mc_p->port_used[i] = 0;
    497         l2mc_p->hg_stream[i] = 0;
    498     }
    499 
    500     /* a trick to accelerate port grouping, if same speed eth and hg */
    501     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    502         if (IS_HG_PORT(unit, l2mc_p->port_list[i])) {
    503             l2mc_p->port_speed[i] |= 0x1;
    504         }
    505     }
    506 
    507     while (ports_accounted_for < l2mc_p->num_fp_ports) {
    508         do {
    509             i = sal_rand() % l2mc_p->num_fp_ports;
    510         }while (l2mc_p->port_used[i] != 0);
    511         stream_possible = 0;
    512         ports_found = 0;
    513         for (j = 0;j < l2mc_p->num_fp_ports; j++) {
    514             if((l2mc_p->port_used[j] == 0) &&
    515                (l2mc_p->port_speed[i] == l2mc_p->port_speed[j]) &&
    516                (i != j)) {
    517                 ports_found++;
    518             }
    519 
    520             if (ports_found >= l2mc_p->num_copy_param) {
    521                 stream_possible = 1;
    522             }
    523         }
    524 
    525         ports_accounted_for++;
    526         if(stream_possible == 1) {
    527             l2mc_p->port_used[i] = 1;
    528             ports_picked = 0;
    529             l2mc_p->stream[l2mc_p->num_streams][0] = i;
    530             if (IS_HG_PORT(unit, l2mc_p->port_list[i])) {
    531                 l2mc_p->hg_stream[l2mc_p->num_streams] = 1;
    532             }
    533             while (ports_picked < l2mc_p->num_copy_param) {
    534                 do {
    535                     picked_port = sal_rand() % l2mc_p->num_fp_ports;
    536                 }while((l2mc_p->port_speed[i] !=
    537                                 l2mc_p->port_speed[picked_port])
    538                         || (l2mc_p->port_used[picked_port] != 0));
    539 
    540                 ports_picked++;
    541                 l2mc_p->port_used[picked_port] = 1;
    542                 l2mc_p->stream[l2mc_p->num_streams][ports_picked]
    543                                                             = picked_port;
    544                 ports_accounted_for++;
    545             }
    546             l2mc_p->num_streams++;
    547         }
    548     }
    549 
    550     /* restore hg speed */
    551     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    552         if (IS_HG_PORT(unit, l2mc_p->port_list[i])) {
    553             l2mc_p->port_speed[i] &= ~0x1;
    554         }
    555     }
    556     l2mc_set_lowest_stream_port(unit);
    557 
    558     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
    559         for (j = 0; j < TARGET_CELL_COUNT; j++) {
    560             do {
    561                 /* coverity[dont_call : FALSE] */
    562                 pkt_size = (sal_rand() % (MTU - MIN_PKT_SIZE + 1)) + MIN_PKT_SIZE;
    563             } while (stream_get_pkt_cell_cnt(unit, pkt_size,
    564                                              l2mc_p->port_list[i]) >
    565                      l2mc_p->max_num_cells_param);
    566             l2mc_p->rand_pkt_sizes[i][j] = pkt_size;
    567         }
    568     }
    569 
    570     {
    571         /* print */
    572         l2mc_print_port_config(unit);
    573         cli_out("\n=========== STREAM INFO ============\n");
    574         cli_out("\n%8s %8s", "Stream", "Port");
    575         for (i = 0; i < l2mc_p->num_streams; i++) {
    576             cli_out("\n%8d ", i);
    577             for (j = 0; j < (l2mc_p->num_copy_param + 1); j++) {
    578                 cli_out("%8d", l2mc_p->port_list[l2mc_p->stream[i][j]]);
    579             }
    580         }
    581     }
    582 }
    583 
    584 /*
    585  * Function:
    586  *      fp_chg_vlan_and_redirect
    587  * Purpose:
    588  *      Creates entry pointed to by l2mc_index in the L2MC table with
    589  *      PORT_BITMAP=redirect_pbmp
    590  *      Create the following FP actions:
    591  *          Qualifier: OuterVlan=old_vlan
    592  *          Actions: OuterVlanNew=VLAN1, RedirectMcast=l2mc_index
    593  * Parameters:
    594  *      unit: StrataSwitch Unit #.
    595  *      old_vlan : Old VLAN of incoming packet
    596  *      new_vlan: New VLAN after IFP modifies packet
    597  *      fg : Pointer to Field group for IFP entry
    598  *      l2mc_index: Index in L2MC table where entry is to be created
    599  *      redirect_pbmp: PORT_BITMAP field of L2MC entry created
    600  * Returns:
    601  *     Nothing
    602  */
    603 static void
    604 l2mc_fp_change_vlan_redirect(int unit, bcm_vlan_t old_vlan, bcm_vlan_t new_vlan,
    605                         bcm_field_group_t *fg, uint32 l2mc_index,
    606                         soc_pbmp_t *redirect_pbmp) {
    607     bcm_field_entry_t fe;
    608     l2mc_entry_t l2mc_entry;
    609 
    610     if (SOC_MEM_IS_VALID(unit, L2MCm)) {
    611         (void) soc_mem_read(unit, L2MCm, COPYNO_ALL, l2mc_index,
    612                             l2mc_entry.entry_data);
    613         soc_mem_field32_set(unit, L2MCm, l2mc_entry.entry_data,
    614                             VALIDf, 0x1);
    615         soc_mem_pbmp_field_set(unit, L2MCm, l2mc_entry.entry_data,
    616                                PORT_BITMAPf, redirect_pbmp);
    617         (void) soc_mem_write(unit, L2MCm, COPYNO_ALL, l2mc_index, 
    618                              l2mc_entry.entry_data);
    619     } else {
    620         cli_out("\n*ERROR, invalid mem %s\n", SOC_MEM_NAME(unit, L2MCm));
    621     }
    622 
    623     (void) bcm_field_entry_create(unit, *fg, &fe);
    624     bcm_field_qualify_OuterVlan(unit, fe, old_vlan, (bcm_vlan_t)(0xffff));
    625     bcm_field_action_add(unit, fe, bcmFieldActionOuterVlanNew,
    626                                                 (uint32)(new_vlan), 0);
    627     bcm_field_action_add(unit, fe, bcmFieldActionRedirectMcast, l2mc_index, 0);
    628     (void) bcm_field_entry_install(unit, fe);
    629 }
    630 
    631 /*
    632  * Function:
    633  *      l2mc_set_up_streams
    634  * Purpose:
    635  *      This function actually sets up the L2MC packet flow. Please refer to
    636  *      items 3-6 of the "Test Setup" section of the test description at the
    637  *      beginning of this file.
    638  * Parameters:
    639  *      unit: StrataSwitch Unit #.
    640  *
    641  * Returns:
    642  *     Nothing.
    643  */
    644 static void
    645 l2mc_set_up_streams(int unit)
    646 {
    647     int i, j;
    648     pbmp_t pbm, ubm;
    649     soc_pbmp_t redirect_pbmp;
    650     uint32 vlan = VLAN;
    651     uint32 vlan_0, vlan_1;
    652     uint32 l2mc_index = 1;
    653     bcm_field_group_t fg;
    654     bcm_field_qset_t qset;
    655     l2mc_t *l2mc_p = l2mc_parray[unit];
    656 
    657     l2mc_p->tx_vlan = (uint32*) sal_alloc(l2mc_p->num_streams * sizeof(uint32),
    658                                           "tx_vlan");
    659     BCM_PBMP_CLEAR(ubm);
    660     bcm_vlan_destroy_all(unit);
    661     bcm_vlan_control_set(unit, bcmVlanTranslate, TRUE);
    662 
    663     BCM_FIELD_QSET_INIT(qset);
    664     BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyOuterVlan);
    665     (void) bcm_field_group_create(unit, qset, l2mc_index, &fg);
    666 
    667     (void) bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 1);
    668 
    669     for (i = 0; i < l2mc_p->num_streams; i++) {
    670         if (l2mc_p->hg_stream[i] == 0) {
    671             /*Ethernet Stream*/
    672             BCM_PBMP_CLEAR(pbm);
    673             bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    674             for (j = 0; j < l2mc_p->num_copy_param + 1; j++) {
    675                 BCM_PBMP_PORT_ADD(pbm, l2mc_p->port_list[l2mc_p->stream[i][j]]);
    676             }
    677             bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    678             vlan_0 = vlan;
    679             vlan++;
    680             bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    681             BCM_PBMP_CLEAR(pbm);
    682             BCM_PBMP_PORT_ADD(pbm, l2mc_p->port_list[l2mc_p->stream[i][0]]);
    683             BCM_PBMP_PORT_ADD(pbm, l2mc_p->port_list[l2mc_p->stream[i][1]]);
    684             bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    685             vlan_1 = vlan;
    686             vlan++;
    687             bcm_vlan_translate_add(unit, l2mc_p->port_list[l2mc_p->stream[i][0]],
    688                                    vlan_1, vlan_0, 0);
    689             bcm_vlan_translate_add(unit, l2mc_p->port_list[l2mc_p->stream[i][1]],
    690                                    vlan_0, vlan_1, 0);
    691 
    692             for (j = 2; j < (l2mc_p->num_copy_param + 1); j++) {
    693                 bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    694                 bcm_vlan_translate_add(unit,
    695                                        l2mc_p->port_list[l2mc_p->stream[i][j]],
    696                                        vlan_0, vlan, 0);
    697                 vlan++;
    698             }
    699             l2mc_p->tx_vlan[i] = vlan_0;
    700         } else {
    701             /*HG2 Stream*/
    702             BCM_PBMP_CLEAR(pbm);
    703             bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    704             BCM_PBMP_PORT_ADD(pbm, l2mc_p->port_list[l2mc_p->stream[i][0]]);
    705             bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    706             vlan_0 = vlan;
    707             vlan++;
    708             bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    709             BCM_PBMP_CLEAR(pbm);
    710             for (j = 0; j < l2mc_p->num_copy_param + 1; j++) {
    711                 BCM_PBMP_PORT_ADD(pbm, l2mc_p->port_list[l2mc_p->stream[i][j]]);
    712             }
    713             bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    714             vlan_1 = vlan;
    715             vlan++;
    716 
    717             SOC_PBMP_CLEAR(redirect_pbmp);
    718             SOC_PBMP_PORT_ADD(redirect_pbmp,
    719                               l2mc_p->port_list[l2mc_p->stream[i][0]]);
    720             l2mc_fp_change_vlan_redirect(unit, vlan_0, vlan_1, &fg,
    721                                     l2mc_index, &redirect_pbmp);
    722             l2mc_index++;
    723 
    724             BCM_PBMP_CLEAR(pbm);
    725             bcm_vlan_create(unit, (bcm_vlan_t)(vlan));
    726             for (j = 1; j < l2mc_p->num_copy_param + 1; j++) {
    727                 BCM_PBMP_PORT_ADD(pbm, l2mc_p->port_list[l2mc_p->stream[i][j]]);
    728             }
    729             bcm_vlan_port_add(unit, (bcm_vlan_t)(vlan), pbm, ubm);
    730             l2mc_fp_change_vlan_redirect(unit, vlan, vlan_1, &fg,
    731                                     l2mc_index, &redirect_pbmp);
    732             l2mc_index++;
    733             SOC_PBMP_CLEAR(redirect_pbmp);
    734             for (j = 1; j < l2mc_p->num_copy_param + 1; j++) {
    735                 SOC_PBMP_PORT_ADD(redirect_pbmp,
    736                                   l2mc_p->port_list[l2mc_p->stream[i][j]]);
    737             }
    738             l2mc_fp_change_vlan_redirect(unit, vlan_1, vlan, &fg,
    739                                     l2mc_index, &redirect_pbmp);
    740             l2mc_index++;
    741             vlan++;
    742             l2mc_p->tx_vlan[i] = vlan_0;
    743         }
    744     }
    745 }
    746 
    747 /*
    748  * Function:
    749  *      l2mc_lossless_flood_cnt
    750  * Purpose:
    751  *      Calculates number of packets that need to be sent to a port for a
    752  *      lossless swirl.
    753  * Parameters:
    754  *      unit - StrataSwitch Unit #.
    755  *      pkt_size : Packet size in bytes
    756  *      port: Test port no
    757  * Returns:
    758  *     Number of packets needed for lossless flooding
    759  */
    760 static uint32
    761 l2mc_lossless_flood_cnt(int unit, int port_speed, int stream_hg_en)
    762 {
    763     uint32 flood_cnt = 0;
    764     int param_flood_cnt;
    765     l2mc_t *l2mc_p = l2mc_parray[unit];
    766 
    767     param_flood_cnt = l2mc_p->flood_pkt_cnt_param;
    768 
    769     if (param_flood_cnt == 0) {
    770         switch (port_speed) {
    771             case 10000: flood_cnt = 14; break;
    772             case 10600: flood_cnt = 14; break;
    773             case 25000: flood_cnt = 14; break;
    774             case 26500: flood_cnt = 25; break;
    775             case 40000: flood_cnt = 20; break;
    776             case 42400: flood_cnt = 38; break;
    777             case 50000: flood_cnt = 24; break;
    778             case 53000: flood_cnt = 45; break;
    779             case 100000: flood_cnt = 50; break;
    780             case 106000: flood_cnt = 94; break;
    781             default: flood_cnt = MAX_PKTS_PER_STREAM; break;
    782         }
    783     } else {
    784         flood_cnt = param_flood_cnt;
    785     }
    786 
    787     if (stream_hg_en == 1) {
    788         flood_cnt = 2 * flood_cnt;
    789     }
    790     if (flood_cnt > MAX_PKTS_PER_STREAM) {
    791         flood_cnt = MAX_PKTS_PER_STREAM;
    792     }
    793 
    794     return (flood_cnt);
    795 }
    796 
    797 /*
    798  * Function:
    799  *      l2mc_send_pkts
    800  * Purpose:
    801  *      Send packets from CPU to create a swirl on each stream. Please refer
    802  *      to item 6 of the "Test Setup" portion of the test description at the
    803  *      beginning of this file.
    804  * Parameters:
    805  *      unit - StrataSwitch Unit #.
    806  *
    807  * Returns:
    808  *     Nothing
    809  */
    810 static void
    811 l2mc_send_pkts(int unit)
    812 {
    813     uint8 mac_da[] = MAC_DA;
    814     uint8 mac_sa[] = MAC_SA;
    815     int i, port;
    816     uint32 pkt_size, flood_cnt, pkt_cnt_sum = 0;
    817     uint32 use_random_packet_sizes = 0;
    818     l2mc_t *l2mc_p = l2mc_parray[unit];
    819     stream_pkt_t *tx_pkt;
    820 
    821     tx_pkt = sal_alloc(sizeof(stream_pkt_t), "tx_pkt");
    822     sal_memset(tx_pkt, 0, sizeof(stream_pkt_t));
    823 
    824     if (l2mc_p->pkt_size_param == 1) {
    825         use_random_packet_sizes = 1;
    826     }
    827 
    828     cli_out("\n==================================================");
    829     cli_out("\nSending packets ...\n");
    830     for (i = 0; i < l2mc_p->num_streams; i++) {
    831         port = l2mc_p->stream[i][0];
    832         if (l2mc_p->pkt_size_param == 0) {
    833             if (l2mc_p->hg_stream[i] == 1) {
    834                 pkt_size = HG2_WC_PKT_SIZE;
    835             } else {
    836                 pkt_size = ENET_WC_PKT_SIZE;
    837             }
    838         } else {
    839             pkt_size = l2mc_p->pkt_size_param;
    840         }
    841         flood_cnt = l2mc_lossless_flood_cnt(unit,
    842                             l2mc_p->port_speed[port],
    843                             l2mc_p->hg_stream[i]);
    844 
    845         tx_pkt->port = l2mc_p->port_list[port];
    846         tx_pkt->num_pkt = flood_cnt;
    847         tx_pkt->pkt_seed = l2mc_p->pkt_seed + i;
    848         tx_pkt->pkt_size = pkt_size;
    849         tx_pkt->rand_pkt_size_en = use_random_packet_sizes;
    850         tx_pkt->rand_pkt_size = NULL;
    851         tx_pkt->tx_vlan = l2mc_p->tx_vlan[i];
    852         sal_memcpy(tx_pkt->mac_da, mac_da, NUM_BYTES_MAC_ADDR);
    853         sal_memcpy(tx_pkt->mac_sa, mac_sa, NUM_BYTES_MAC_ADDR);
    854         if (tx_pkt->rand_pkt_size_en) {
    855             tx_pkt->rand_pkt_size = l2mc_p->rand_pkt_sizes[port];
    856         }
    857         stream_tx_pkt(unit, tx_pkt);
    858         /* print */
    859         cli_out("Stream %0d, pkt_flood_count = %0d\n", i, tx_pkt->cnt_pkt);
    860         pkt_cnt_sum += tx_pkt->cnt_pkt;
    861     }
    862 
    863     cli_out("\nTotal packets sent: %0d\n\n", pkt_cnt_sum);
    864     sal_free(tx_pkt);
    865 }
    866 
    867 /*
    868  * Function:
    869  *      l2mc_set_up_ports
    870  * Purpose:
    871  *      1. Enable IFP for CPU port
    872  *      2. Program ING_VLAN_TAG_ACTION_PROFILE to remove inner tag for double
    873  *         tagged packets
    874  *      3. Program MMU to not accept any packets from ports l2mc_p->stream[i][2..n]
    875  *         by setting THDI_INPUT_PORT_XON_ENABLES.INPUT_PORT_RX_ENABLE=0.
    876  *         This prevents the number of packets in each swill from multiplying.
    877  *      4. Set IGNORE_MY_MODID to 1 to prevent dropping HG2 packets after looping
    878  *         back.
    879  * Parameters:
    880  *      unit - StrataSwitch Unit #.
    881  *
    882  * Returns:
    883  *     Nothing
    884  */
    885 static void
    886 l2mc_set_up_ports(int unit)
    887 {
    888     int i, j;
    889     port_tab_entry_t port_tab_entry;
    890     l2mc_t *l2mc_p = l2mc_parray[unit];
    891     ing_vlan_tag_action_profile_entry_t ing_vlan_tag_action_profile_entry;
    892     uint64 ing_config;
    893 
    894     if (SOC_MEM_IS_VALID(unit, PORT_TABm)) {
    895         (void) soc_mem_read(unit, PORT_TABm, COPYNO_ALL,
    896                         CPU_PORT, port_tab_entry.entry_data);
    897         soc_mem_field32_set(unit, PORT_TABm, port_tab_entry.entry_data,
    898                             FILTER_ENABLEf, 0x1);
    899         (void) soc_mem_write(unit, PORT_TABm, COPYNO_ALL, CPU_PORT,
    900                         port_tab_entry.entry_data);
    901     } else {
    902         cli_out("\n*ERROR, invalid mem %s\n", SOC_MEM_NAME(unit, PORT_TABm));
    903     }
    904 
    905     if (SOC_MEM_IS_VALID(unit, ING_VLAN_TAG_ACTION_PROFILEm)) {
    906         (void) soc_mem_read(unit, ING_VLAN_TAG_ACTION_PROFILEm, COPYNO_ALL,
    907                      0, ing_vlan_tag_action_profile_entry.entry_data);
    908         soc_mem_field32_set(unit, ING_VLAN_TAG_ACTION_PROFILEm,
    909                             ing_vlan_tag_action_profile_entry.entry_data,
    910                             DT_ITAG_ACTIONf, 0x3);
    911         (void) soc_mem_write(unit, ING_VLAN_TAG_ACTION_PROFILEm, COPYNO_ALL,
    912                      0, ing_vlan_tag_action_profile_entry.entry_data);
    913 
    914     } else {
    915         cli_out("\n*ERROR, invalid mem %s\n",
    916                 SOC_MEM_NAME(unit, ING_VLAN_TAG_ACTION_PROFILEm));
    917     }
    918 
    919     if (SOC_REG_IS_VALID(unit, THDI_INPUT_PORT_XON_ENABLESr)) {
    920         for (i = 0; i < l2mc_p->num_streams; i++) {
    921             for (j = 2; j < (l2mc_p->num_copy_param + 1); j++) {
    922                 soc_reg_field32_modify(unit, THDI_INPUT_PORT_XON_ENABLESr,
    923                                        l2mc_p->port_list[l2mc_p->stream[i][j]],
    924                                        INPUT_PORT_RX_ENABLEf, 0x0);
    925             }
    926         }
    927     } else {
    928         cli_out("\n*ERROR, invalid reg %s\n",
    929                 SOC_REG_NAME(unit, THDI_INPUT_PORT_XON_ENABLESr));
    930     }
    931 
    932     if (SOC_REG_IS_VALID(unit, ING_CONFIG_64r)) {
    933         (void) soc_reg_get(unit, ING_CONFIG_64r, REG_PORT_ANY, 0, &ing_config);
    934         soc_reg64_field32_set(unit, ING_CONFIG_64r, &ing_config,
    935                               IGNORE_MY_MODIDf, 0x1);
    936         (void) soc_reg_set(unit, ING_CONFIG_64r, REG_PORT_ANY, 0, ing_config);
    937     } else {
    938         cli_out("\n*ERROR, invalid reg %s\n",
    939                 SOC_REG_NAME(unit, ING_CONFIG_64r));
    940     }
    941 }
    942 
    943 /*
    944  * Function:
    945  *      l2mc_chk_port_rate
    946  * Purpose:
    947  *      Check actual port rates against expected port rates.
    948  * Parameters:
    949  *      unit - StrataSwitch Unit #.
    950  *
    951  * Returns:
    952  *     SOC_E_XXXX
    953  */
    954 static bcm_error_t
    955 l2mc_chk_port_rate(int unit)
    956 {
    957     int i, j, port, port_idx;
    958     bcm_error_t rv = BCM_E_NONE;
    959     stream_rate_t *rate_calc;
    960     l2mc_t *l2mc_p = l2mc_parray[unit];
    961 
    962     rate_calc = (stream_rate_t *)
    963                  sal_alloc(sizeof(stream_rate_t), "rate_calc");
    964     if (rate_calc == NULL) {
    965         test_error(unit, "Failed to allocate memory for rate_calc\n");
    966         return BCM_E_FAIL;
    967     }
    968     sal_memset(rate_calc, 0, sizeof(stream_rate_t));
    969 
    970     rate_calc->mode         = 0; /* check act_rate against config_rate */
    971     rate_calc->pkt_size     = l2mc_p->pkt_size_param;
    972     rate_calc->interval_len = l2mc_p->rate_calc_interval_param;
    973     rate_calc->tolerance_lr = l2mc_p->rate_tolerance_lr_param;
    974     rate_calc->tolerance_os = l2mc_p->rate_tolerance_ov_param;
    975     rate_calc->scaling_factor = l2mc_p->scaling_factor_param;
    976 
    977     SOC_PBMP_CLEAR(rate_calc->pbmp);
    978     for (i = 0; i < l2mc_p->num_streams; i++) {
    979         for (j = 0; j < (l2mc_p->num_copy_param + 1); j++) {
    980             port_idx = l2mc_p->stream[i][j];
    981             port = l2mc_p->port_list[port_idx];
    982             if (port < SOC_MAX_NUM_PORTS) {
    983                 /* pbmp */
    984                 SOC_PBMP_PORT_ADD((rate_calc->pbmp), port);
    985                 /* num_rep */
    986 /*                 if (l2mc_p->l3_copy[port_idx] == 0) {
    987                     rate_calc->num_rep[port] = 0;
    988                 } else {
    989                     rate_calc->num_rep[port] = l2mc_p->num_rep[port_idx] + 1;
    990                 } */
    991                 /* src_port */
    992                 rate_calc->src_port[port] =
    993                         l2mc_p->port_list[l2mc_p->stream[i][1]];
    994             }
    995         }
    996     }
    997 
    998     rv = stream_chk_port_rate(unit, PBMP_PORT_ALL(unit), rate_calc);
    999 
   1000     sal_free(rate_calc);
   1001     return rv;
   1002 }
   1003 
   1004 /*
   1005  * Function:
   1006  *      l2mc_hg_disable_vlan_ports
   1007  * Purpose:
   1008  *      Workaround to diasble vlan PORT_BITMAP,
   1009  *      to avoid forwarding between vlan ports after vlan disable
   1010  * Parameters:
   1011  *      unit - StrataSwitch Unit #.
   1012  *      disable - disable vlan ports
   1013  *
   1014  * Returns:
   1015  *     Nothing
   1016  */
   1017 static void
   1018 l2mc_hg_disable_vlan_ports(int unit, int disable)
   1019 {
   1020     int i, vlan, param_num_stream, stream_hg_en;
   1021     l2mc_t *l2mc_p = l2mc_parray[unit];
   1022     vlan_2_tab_entry_t vlan_2_tab_entry;
   1023     soc_pbmp_t pbm;
   1024 
   1025     if (!SOC_IS_TOMAHAWKX(unit)) {
   1026         return;
   1027     }
   1028 
   1029     param_num_stream = l2mc_p->num_streams;
   1030     for (i = 0; i < param_num_stream; i++) {
   1031         stream_hg_en = l2mc_p->hg_stream[i];
   1032         if (!stream_hg_en) {
   1033             continue;
   1034         }
   1035 
   1036         vlan = l2mc_p->tx_vlan[i] + 1;
   1037         (void) soc_mem_read(unit, VLAN_2_TABm, COPYNO_ALL, vlan,
   1038                             vlan_2_tab_entry.entry_data);
   1039         if (disable) {
   1040             SOC_PBMP_CLEAR(pbm);
   1041         } else {
   1042             (void) soc_mem_pbmp_field_get(unit, VLAN_2_TABm,
   1043                 vlan_2_tab_entry.entry_data, ING_PORT_BITMAPf, &pbm);
   1044         }
   1045         (void) soc_mem_pbmp_field_set(unit, VLAN_2_TABm,
   1046             vlan_2_tab_entry.entry_data, PORT_BITMAPf, &pbm);
   1047         (void) soc_mem_write(unit, VLAN_2_TABm, COPYNO_ALL, vlan,
   1048                              vlan_2_tab_entry.entry_data);
   1049     }
   1050 }
   1051 
   1052 /*
   1053  * Function:
   1054  *      l2mc_chk_pkt_integrity
   1055  * Purpose:
   1056  *      Redirect all packets back to CPU and check packet integrity
   1057  * Parameters:
   1058  *      unit - StrataSwitch Unit #.
   1059  *
   1060  * Returns:
   1061  *     Nothing
   1062  */
   1063 static bcm_error_t
   1064 l2mc_chk_pkt_integrity(int unit)
   1065 {
   1066     int i, port, port_speed, stream_hg_en, vlan_id;
   1067     int param_num_stream, param_pkt_seed;
   1068     int *param_port_list, **param_stream, *param_port_speed,
   1069         *param_hg_stream;
   1070     uint32 flood_cnt;
   1071     uint8 mac_da[] = MAC_DA;
   1072     uint8 mac_sa[] = MAC_SA;
   1073     stream_integrity_t *pkt_intg;
   1074     bcm_error_t rv = BCM_E_NONE;
   1075     l2mc_t *l2mc_p = l2mc_parray[unit];
   1076 
   1077     param_num_stream = l2mc_p->num_streams;
   1078     param_pkt_seed = l2mc_p->pkt_seed;
   1079     param_port_list = l2mc_p->port_list;
   1080     param_stream = l2mc_p->stream;
   1081     param_port_speed = l2mc_p->port_speed;
   1082     param_hg_stream = l2mc_p->hg_stream;
   1083 
   1084     pkt_intg = sal_alloc(sizeof(stream_integrity_t), "pkt_intg");
   1085     if (pkt_intg == NULL) {
   1086         test_error(unit, "Failed to allocate memory for pkt_intg\n");
   1087         return BCM_E_FAIL;
   1088     }
   1089     sal_memset(pkt_intg, 0, sizeof(stream_integrity_t));
   1090 
   1091     pkt_intg->type = PKT_TYPE_L2;
   1092     SOC_PBMP_CLEAR(pkt_intg->rx_pbmp);
   1093     for (i = 0; i < param_num_stream; i++) {
   1094         port = param_port_list[param_stream[i][0]];
   1095         port_speed = param_port_speed[param_stream[i][0]];
   1096         stream_hg_en = param_hg_stream[i];
   1097         if (port < SOC_MAX_NUM_PORTS) {
   1098             /* rx_pbmp */
   1099             SOC_PBMP_PORT_ADD(pkt_intg->rx_pbmp, port);
   1100 
   1101             /* rx_vlan: used to forward pkt to CPU */
   1102             if (stream_hg_en == 1) {
   1103                 vlan_id = l2mc_p->tx_vlan[i] + 1;
   1104             } else {
   1105                 vlan_id = l2mc_p->tx_vlan[i];
   1106             }
   1107             pkt_intg->rx_vlan[port] = vlan_id;
   1108 
   1109             /* tx_vlan: used to re-generate ref_pkt */
   1110             vlan_id = l2mc_p->tx_vlan[i] + 1;
   1111             pkt_intg->tx_vlan[port] = vlan_id;
   1112 
   1113             /* port_flood_cnt */
   1114             flood_cnt = l2mc_lossless_flood_cnt(unit, port_speed, stream_hg_en);
   1115             if (stream_hg_en == 0) {
   1116                 flood_cnt = 2 * flood_cnt;
   1117             }
   1118             pkt_intg->port_flood_cnt[port] = flood_cnt;
   1119 
   1120             /* port_pkt_seed */
   1121             pkt_intg->port_pkt_seed[port] = param_pkt_seed + i;
   1122 
   1123             /* mac_da, mac_sa */
   1124             sal_memcpy(pkt_intg->mac_da[port], mac_da, NUM_BYTES_MAC_ADDR);
   1125             sal_memcpy(pkt_intg->mac_sa[port], mac_sa, NUM_BYTES_MAC_ADDR);
   1126         }
   1127     }
   1128 
   1129     l2mc_hg_disable_vlan_ports(unit, 1);
   1130     if (stream_chk_pkt_integrity(unit, pkt_intg) != BCM_E_NONE) {
   1131         rv = BCM_E_FAIL;
   1132     }
   1133     l2mc_hg_disable_vlan_ports(unit, 0);
   1134 
   1135     sal_free(pkt_intg);
   1136     return rv;
   1137 }
   1138 
   1139 /*
   1140  * Function:
   1141  *      l2mc_test_init
   1142  * Purpose:
   1143  *      Test init function. Parse CLI params and do necessary init.
   1144  * Parameters:
   1145  *      unit - StrataSwitch Unit #.
   1146  *
   1147  * Returns:
   1148  *     Nothing
   1149  */
   1150 int
   1151 l2mc_test_init(int unit, args_t *a, void **pa)
   1152 {
   1153     l2mc_t *l2mc_p;
   1154 
   1155     l2mc_p = l2mc_parray[unit];
   1156     l2mc_p = sal_alloc(sizeof(l2mc_t), "l2mc_test");
   1157     sal_memset(l2mc_p, 0, sizeof(l2mc_t));
   1158     l2mc_parray[unit] = l2mc_p;
   1159     cli_out("\n==================================================");
   1160     cli_out("\nCalling l2mc_test_init ...\n");
   1161     l2mc_parse_test_params(unit, a);
   1162 
   1163     l2mc_p->test_fail = 0;
   1164 
   1165     if (l2mc_p->bad_input == 1) {
   1166         goto done;
   1167     }
   1168 
   1169     stream_set_mac_lpbk(unit, PBMP_PORT_ALL(unit));
   1170     stream_turn_off_cmic_mmu_bkp(unit);
   1171     stream_turn_off_fc(unit, PBMP_PORT_ALL(unit));
   1172     /* coverity[dont_call : FALSE] */
   1173     l2mc_p->pkt_seed = sal_rand();
   1174 
   1175 done:
   1176     return 0;
   1177 }
   1178 
   1179 /*
   1180  * Function:
   1181  *      l2mc_test
   1182  * Purpose:
   1183  *      Set up ports/streams and send packets.
   1184  * Parameters:
   1185  *      unit - StrataSwitch Unit #.
   1186  *
   1187  * Returns:
   1188  *     Nothing
   1189  */
   1190 int
   1191 l2mc_test(int unit, args_t *a, void *pa)
   1192 {
   1193     l2mc_t *l2mc_p = l2mc_parray[unit];
   1194 
   1195     if (l2mc_p->bad_input == 1) {
   1196         goto done;
   1197     }
   1198 
   1199     cli_out("\n==================================================");
   1200     cli_out("\nCalling l2mc_test ... \n");
   1201     l2mc_set_port_property_arrays(unit);
   1202     l2mc_set_up_ports(unit);
   1203     l2mc_set_up_streams(unit);
   1204     l2mc_send_pkts(unit);
   1205 
   1206     /* check counter */
   1207     if (stream_chk_mib_counters(unit, PBMP_PORT_ALL(unit), 0) != BCM_E_NONE) {
   1208         l2mc_p->test_fail = 1;
   1209     }
   1210     /* check rate */
   1211     if (l2mc_chk_port_rate(unit) != BCM_E_NONE) {
   1212         l2mc_p->test_fail = 1;
   1213     }
   1214     /* check integrity */
   1215     if (l2mc_chk_pkt_integrity(unit) != BCM_E_NONE) {
   1216         l2mc_p->test_fail = 1;
   1217     }
   1218 
   1219 done:
   1220     return 0;
   1221 }
   1222 
   1223 /*
   1224  * Function:
   1225  *      l2mc_test_cleanup
   1226  * Purpose:
   1227  *      Do test end checks and free all allocated memory.
   1228  * Parameters:
   1229  *      unit - StrataSwitch Unit #.
   1230  *
   1231  * Returns:
   1232  *     Nothing
   1233  */
   1234 int
   1235 l2mc_test_cleanup(int unit, void *pa)
   1236 {
   1237     int i, rv;
   1238     l2mc_t *l2mc_p = l2mc_parray[unit];
   1239 
   1240     if (l2mc_p->bad_input == 1) {
   1241         goto done;
   1242     }
   1243     cli_out("\nCalling l2mc_test_cleanup");
   1244 
   1245     /* free memory */
   1246     sal_free(l2mc_p->port_speed);
   1247     sal_free(l2mc_p->port_list);
   1248     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
   1249         sal_free(l2mc_p->stream[i]);
   1250     }
   1251     sal_free(l2mc_p->stream);
   1252     sal_free(l2mc_p->tx_vlan);
   1253     sal_free(l2mc_p->hg_stream);
   1254     sal_free(l2mc_p->port_oversub);
   1255     sal_free(l2mc_p->ovs_ratio_x1000);
   1256     sal_free(l2mc_p->rate);
   1257     sal_free(l2mc_p->exp_rate);
   1258     sal_free(l2mc_p->tpkt_start);
   1259     sal_free(l2mc_p->tpkt_end);
   1260     sal_free(l2mc_p->tbyt_start);
   1261     sal_free(l2mc_p->tbyt_end);
   1262 
   1263     for (i = 0; i < l2mc_p->num_fp_ports; i++) {
   1264         sal_free(l2mc_p->rand_pkt_sizes[i]);
   1265     }
   1266     sal_free(l2mc_p->rand_pkt_sizes);
   1267 
   1268 done:
   1269     if (l2mc_p->bad_input == 1) {
   1270         l2mc_p->test_fail = 1;
   1271     }
   1272 
   1273     if (l2mc_p->test_fail == 1) {
   1274         rv = BCM_E_FAIL;
   1275     }
   1276     else {
   1277         rv = BCM_E_NONE;
   1278     }
   1279 
   1280     cli_out("\n==================================================");
   1281     cli_out("\n==================================================");
   1282     if (l2mc_p->test_fail == 1) {
   1283         cli_out("\n[L2MC test failed]\n\n");
   1284     } else {
   1285         cli_out("\n[L2MC test passed]\n\n");
   1286     }
   1287     sal_free(l2mc_p);
   1288 
   1289     return rv;
   1290 }
   1291 #endif /* BCM_ESW_SUPPORT */